syncthing / syncthing-macos

Official frugal and native macOS Syncthing application bundle
https://syncthing.net
MIT License
2.72k stars 146 forks source link

Fix package signing #8

Closed rjmackay closed 7 years ago

rjmackay commented 8 years ago

It not reasonable to disable gatekeeper for my whole machine to install a single application. Any idea when package signing will be fixed?

xor-gate commented 8 years ago

Hi @rjmackay,

It will be the first thing i'm going to fix but I first need to investigate why the .app is modified after signing in the first place. Hopefully in the upcoming weeks as time permits.

As reference for myself: http://stackoverflow.com/questions/22458027/mac-dmg-oddity-signing-and-damaged-applications

justinclift commented 8 years ago

Taking a quick look here (I'm no expert though), it seems to be a problem with the bundled Sparkle framework:

$ codesign --verify --verbose --deep Syncthing.app
Syncthing.app: a sealed resource is missing or invalid
In subcomponent: /Users/jc/tmp/Syncthing.app/Contents/Frameworks/Sparkle.framework
file added: /Users/jc/tmp/Syncthing.app/Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/fr_CA.lproj/Sparkle.strings
file added: /Users/jc/tmp/Syncthing.app/Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/fr_CA.lproj/SUAutomaticUpdateAlert.nib
file added: /Users/jc/tmp/Syncthing.app/Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/fr_CA.lproj/SUUpdateAlert.nib
file added: /Users/jc/tmp/Syncthing.app/Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/fr_CA.lproj/SUUpdatePermissionPrompt.nib
file added: /Users/jc/tmp/Syncthing.app/Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/pt.lproj/Sparkle.strings
file added: /Users/jc/tmp/Syncthing.app/Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/pt.lproj/SUAutomaticUpdateAlert.nib
file added: /Users/jc/tmp/Syncthing.app/Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/pt.lproj/SUUpdateAlert.nib
file added: /Users/jc/tmp/Syncthing.app/Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/pt.lproj/SUUpdatePermissionPrompt.nib
file missing: /Users/jc/tmp/Syncthing.app/Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/fr_CA.lproj
file missing: /Users/jc/tmp/Syncthing.app/Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/pt.lproj

There seem to be two sets of strings (fr_CA, pt) modified from when it was signed.

It might be as simple as just needing an updated version of the Sparkle framework, or just re-signing it. :smile:

xor-gate commented 8 years ago

Hi @justinclift thanks for you help!

I have read the sparkle documentation:

Apple code signing

If you are code-signing your application via Apple’s Developer ID program (which is recommended for macOS 10.8+), Sparkle will ensure the new version’s author matches the old version’s. Sparkle also performs basic (but not deep) validation for testing if the new application is archived/distributed correctly as you intended.

Note that embedding the Sparkle.framework into the bundle of a Developer ID application requires that you code-sign the framework with your Developer ID keys. Xcode should do this automatically if you let it “Code Sign on Copy” Sparkle’s framework. You can diagnose code signing problems with RB App Checker app and by checking logs in the Console.app. If you decide to both code-sign your application and include a public DSA key for signing your update archive, Sparkle allows issuing a new update that changes either your code signing certificate or your DSA keys. Note however this is a last resort and should only be done if you lose access to one of them.

The project uses the "Code Sign on Copy" for the Sparkle framework. But this seems to be a different problem. I have found another nice tool to check the validity with more output (GUI): RB App Checker Lite

Which gives:

Evaluating the application “Syncthing”.

The application was signed by “Apple Root CA”, “Mac Developer: jerryjacobs1989@gmail.com (TT7GM4W59N)”.
    The (unverified) signing-time is: 23 Aug 2016 19:27:13.
    The object code format is “app bundle with Mach-O thin (x86_64)”.
    The signature contains the Team ID “C24U83K674”.
    Both bundle and signing identifiers are “com.github.xor-gate.syncthing-macosx”.
    The signature specifies implicit requirements. 
    The signature specifies resource rules (v1). 
    The signature specifies resource rules (v2). 
    ➤ Requirements and resources didn't pass static validation.  

The code signature has the UUID “CAE07AC2-B487-88EE-E762-905692B17C16”.
    Executable code for x86_64 has the UUID “D55BA232-79EB-3AA7-86C5-978EC2989411”.

A signing-time snapshot of the application’s Info.plist was found. 
    Version 0.14.5 (140500) Copyright © 2016 Jerry Jacobs (github.com/xor-gate). All rights reserved.

The signature contains 3 certificates. 
    Certificate “Apple Root CA”: 
        Your keychain contains this trusted root certificate.
        Will expire on 09 Feb 2035.
    Certificate “Apple Worldwide Developer Relations Certification Authority”: 
        Will expire on 07 Feb 2023.
    Certificate “Mac Developer: jerryjacobs1989@gmail.com (TT7GM4W59N)”: 
        Will expire on 07 Aug 2017.
        SHA1 fingerprint: “8433783E947D054D7B88A70B0ACDB95B9CF3DAAF”.
        Team ID or Organizational Unit: “C24U83K674”.
            This matches the Team ID contained in the signature.

The application is not sandboxed.

There is one embedded framework. 

10 auxiliary executables have been found. 
    One file is invisible in the Finder.  
    6 executables are unsigned.  
    One executable is signed by  “Apple Root CA”, “Developer ID Application: Jakob Borg (LQE5SYM783)”. 
    3 executables are signed by  “Apple Root CA”, “Mac Developer: jerryjacobs1989@gmail.com (TT7GM4W59N)”. 
    4 executables are in the Resources folder. 
    One executable file has no executable permissions, but should.  
    Different executables are using the same signing identifier “org.sparkle-project.Sparkle”. 
    Different executables are using the same bundle identifier “org.sparkle-project.Sparkle”. 

And:

Error details: “-67054: a sealed resource is missing or invalid” {
    Error in subcomponent: Contents/Frameworks/Sparkle.framework
    Resources added: 
        Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/fr_CA.lproj/SUAutomaticUpdateAlert.nib
        Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/fr_CA.lproj/SUUpdateAlert.nib
        Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/fr_CA.lproj/Sparkle.strings
        Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/fr_CA.lproj/SUUpdatePermissionPrompt.nib
        Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/pt.lproj/SUAutomaticUpdateAlert.nib
        Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/pt.lproj/SUUpdateAlert.nib
        Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/pt.lproj/SUUpdatePermissionPrompt.nib
        Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/pt.lproj/Sparkle.strings
    Resources missing: 
        Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/fr_CA.lproj
        Contents/Frameworks/Sparkle.framework/Versions/Current/Resources/pt.lproj
}

No clue about the solution yet. I can ask the guys from Sparkle.

justinclift commented 8 years ago

Yeah, it's probably a good idea to ask the Sparkle guys, as the Resources added and Resources missing indicate things in their signed file set changed unexpectedly. They probably know about this already, and have re-signed them since. 😉

As a quick workaround, you could sign the Sparkle framework bundled inside your Syncthing.app, but it's probably better to ping the Sparkle guys first. :smile:

xor-gate commented 8 years ago

This is weird, when I don't put the .app into the DMG then it is not broken! Can you guys test out? I have build a new one (0.14.5) and packed it inside a zipfile.

https://github.com/xor-gate/syncthing-macosx/releases/download/v0.14.5/Syncthing-0.14.5-signed.zip

I have verified with RB App Checker Lite.

justinclift commented 8 years ago

Yeah, that one seems fine to me:

$ codesign --verify --verbose --deep Syncthing.app
Syncthing.app: valid on disk
Syncthing.app: satisfies its Designated Requirement
xor-gate commented 8 years ago

I must say, pushing the .app into the dmg is not the best way how it is done currently. Probably the script will break somewhere. Needs some investigation...

justinclift commented 8 years ago

Ahhhh, found something interesting. The end part of the "unzip" output on your zip file was:

finishing deferred symbolic links:
  Syncthing.app/Contents/Frameworks/Sparkle.framework/Resources -> Versions/Current/Resources
  Syncthing.app/Contents/Frameworks/Sparkle.framework/Sparkle -> Versions/Current/Sparkle
  Syncthing.app/Contents/Frameworks/Sparkle.framework/Versions/A/Resources/fr_CA.lproj -> fr.lproj
  Syncthing.app/Contents/Frameworks/Sparkle.framework/Versions/A/Resources/pt.lproj -> pt_BR.lproj
  Syncthing.app/Contents/Frameworks/Sparkle.framework/Versions/Current -> A

Both the fr_CA.lproj and pr.lproj look like links. Maybe your .dmg creation process isn't doing the links correctly?

xor-gate commented 8 years ago

Yeah probably how the DMG ramdisk is created and files are copied into is breaking it: https://github.com/xor-gate/syncthing-macosx/blob/master/3thparty/github.com/andreyvit/create-dmg/create-dmg

justinclift commented 8 years ago

If you need an alternative (super simple) way to create .dmg's from your app, you can copy ours if it helps? Example .dmg here:

justinclift commented 8 years ago

That's ironic. create-dmg was the first thing we tried too (a few weeks ago), but it was too buggy. Went with https://github.com/LinusU/node-appdmg instead. 1 min, and I'll dig up the bits.

xor-gate commented 8 years ago

I think I hacked the script. It seems the creation with hdiutils breaks the filesystem. Searched stackoverflow: http://stackoverflow.com/questions/6081503/automating-dmg-build-in-xcode-4-0

Probably it breaks during: https://github.com/xor-gate/syncthing-macosx/blob/master/3thparty/github.com/andreyvit/create-dmg/create-dmg#L214

justinclift commented 8 years ago

The bits:

You can probably just update the values in the json with "Syncthing.app", your own background image (and the 2X), and the X,Y positions and call it a day. :smile:

xor-gate commented 8 years ago

Thanks @justinclift as I have the dmg-building in-place and not a big fan of node-js utiltity scripts. I probably have solved the problem. During staging before creating the DMG the copy didn't preserved the symlinks. Now I have created a new release which should fix it:

https://github.com/xor-gate/syncthing-macosx/releases/download/v0.14.5/Syncthing-0.14.5-testing.dmg

I have done this fix: https://github.com/xor-gate/syncthing-macosx/commit/e41767958917d3dce0bb61e1edfe8d25fd90ef3a

@rjmackay could you also test this new DMG if it works with filevault enabled?

Crossreference to: https://github.com/sparkle-project/Sparkle/issues/433

justinclift commented 8 years ago

Yep, that seems to have fixed it. :smile:

$ codesign --verify --verbose --deep Syncthing.app
Syncthing.app: valid on disk
Syncthing.app: satisfies its Designated Requirement
xor-gate commented 8 years ago

That's awesome! Thank you for your help and testing.

xor-gate commented 8 years ago

I have silently removed the "broken" dmg in the 0.14.5 release and replaced with the fixed one. Also the -testing and zipfile have been removed. Otherwise this would confuse new users.

justinclift commented 8 years ago

You're welcome. :smile:

xor-gate commented 8 years ago

I'm closing this, when there are any problems. Don't hesitate to open a new issue (or continue in this one if there are still problems).

zqye commented 7 years ago

Please sign the the app bundle in release key rather the developer key to make gatekeeper happy.

Now the app is signed with the developer key:

Executable=/Volumes/Syncthing/Syncthing.app/Contents/MacOS/Syncthing Identifier=com.github.xor-gate.syncthing-macosx Format=app bundle with Mach-O thin (x86_64) CodeDirectory v=20200 size=932 flags=0x0(none) hashes=23+3 location=embedded Hash type=sha256 size=32 CandidateCDHash sha1=0f2a975e438011471df9586fdd098cf5b63cece7 CandidateCDHash sha256=8f70bef4824f1922726e5ebec220ee24fdb7ae21 Hash choices=sha1,sha256 CDHash=8f70bef4824f1922726e5ebec220ee24fdb7ae21 Signature size=4696 Authority=Mac Developer: jerryjacobs1989@gmail.com (TT7GM4W59N) Authority=Apple Worldwide Developer Relations Certification Authority Authority=Apple Root CA Signed Time=9 Aug 2016, 6:42:36 PM Info.plist entries=29 TeamIdentifier=C24U83K674 Sealed Resources version=2 rules=12 files=30 Internal requirements count=1 size=208

And gatekeeper prevent me to open it directly even though it is signed correctly. It will make us more convenient if you could sign it in release key.

xor-gate commented 7 years ago

You should allow from gatekeeper Mac App Store and identified developers instead of Mac App Store:

https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/DistributingApplicationsOutside/DistributingApplicationsOutside.html#//apple_ref/doc/uid/TP40012582-CH12-SW2

gatekeeperscreenshot

This because the application is distributed without Mac App Store signed key and will never be.

zqye commented 7 years ago

I have already allow gatekeeper from Mac App Store and identified developers. However,

➜  /Applications codesign -dvv Google\ Chrome.app 
Executable=/Applications/Google Chrome.app/Contents/MacOS/Google Chrome
Identifier=com.google.Chrome
Format=app bundle with Mach-O thin (x86_64)
CodeDirectory v=20200 size=273 flags=0x800(restrict) hashes=3+3 location=embedded
Signature size=8896
Authority=Developer ID Application: Google Inc.
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=8 Nov 2016, 11:19:50 AM
Info.plist entries=34
TeamIdentifier=EQHXZ8M8AV
Sealed Resources version=2 rules=7 files=191
Internal requirements count=1 size=132
➜  /Applications codesign -dvv Syncthing.app 
Executable=/Applications/Syncthing.app/Contents/MacOS/Syncthing
Identifier=com.github.xor-gate.syncthing-macosx
Format=app bundle with Mach-O thin (x86_64)
CodeDirectory v=20200 size=1060 flags=0x0(none) hashes=27+3 location=embedded
Signature size=4696
Authority=Mac Developer: jerryjacobs1989@gmail.com (TT7GM4W59N)
Authority=Apple Worldwide Developer Relations Certification Authority
Authority=Apple Root CA
Signed Time=16 Oct 2016, 11:06:46 PM
Info.plist entries=30
TeamIdentifier=C24U83K674
Sealed Resources version=2 rules=13 files=35
Internal requirements count=1 size=208

The difference is that Google Chrome is signed by certificate type of Developer ID Application but Syncthing is signed by certificate type of Mac Development.

From https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/MaintainingCertificates/MaintainingCertificates.html Table 14-2, Mac Development is used to enable certain app services for a Mac app during development and testing. And it would not pass gatekeeper.

Thus, if you could sign application with certificate of Developer ID Application, it will be easier for us to use the application.

Thanks.

xor-gate commented 7 years ago

I will investigate ASAP (no hard due date).

Clicked close button by accident

justinclift commented 7 years ago

Ahhh yeah, I remember having to do this too. The docs for this are way more complicated than they need to be, which was off-putting.

@xor-gate If you have 5 mins, it's actually pretty simple to do. :smile:

  1. Goto https://developer.apple.com, login there.
  2. On the "Account" page (once logged in) there is a vertical menu on the left. Choose "Certificates, IDs & Profiles" (2nd option from the top).
  3. At the top of the vertical menu on this page, there is a drop down selector with options. Change it to the "OSX" option. Now you'll be in the "Mac Certificates" section.
  4. Click the + symbol on the right:

    screenshot_2016-11-10_13-24-47

  5. Choose "Developer ID", then click continue:

    screenshot_2016-11-10_13-32-16

  6. Choose "Developer ID Application", then click continue:

    screenshot_2016-11-10_13-35-06

  7. That's the selection steps done to get you to the right part. Now just follow the instructions it gives (open Keychain Access utility on your Mac, generate the request (CSR), download your certificate).

That's how I did it anyway.

Hope that helps. :smile:

xor-gate commented 7 years ago

Nope, it doesn't show up. I need to pay the 99 bucks to make it work -> Enable Developer ID.

screen shot 2016-11-10 at 19 30 00
xor-gate commented 7 years ago

Under XCode it looks like this:

target build settings

screen shot 2016-11-10 at 19 47 24

preferences -> accounts

screen shot 2016-11-10 at 19 47 44
xor-gate commented 7 years ago

Last resort: https://support.apple.com/kb/ph18657?locale=en_US

justinclift commented 7 years ago

Ahhhh yeah. Forgot about the $99 thing. Oops. :wink:

xor-gate commented 7 years ago

I will add a note in the README about this, as I'm not going to spend the $99 any time soon.

xor-gate commented 7 years ago

As @virusman is now a project contributor he signed the latest v0.14.33-1 release with his apple developer account. Only the auto-updater (Sparkle) is not yet updated because we changed the keys and is disallowed. As seen below:

screen shot 2017-08-03 at 10 06 25

~/Library/Logs/SparkleUpdateLog.log

2017-08-03 08:06:24 +0000: Code signature of the new version doesn't match the old version: identifier "com.github.xor-gate.syncthing-macosx" and anchor apple generic and certificate leaf[subject.CN] = "Mac Developer: jerryjacobs1989@gmail.com (TT7GM4W59N)" and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */. Please ensure that old and new app is signed using exactly the same certificate.
2017-08-03 08:06:24 +0000: host info: {
    build = 140802;
    format = "app bundle with Mach-O thin (x86_64)";
    identifier = "com.github.xor-gate.syncthing-macosx";
    requirements = "designated => identifier \"com.github.xor-gate.syncthing-macosx\" and anchor apple generic and certificate leaf[subject.CN] = \"Mac Developer: jerryjacobs1989@gmail.com (TT7GM4W59N)\" and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */\n";
    "signing-time" = "2016-10-16 15:06:46 +0000";
    teamid = C24U83K674;
    version = "0.14.8-2";
}
2017-08-03 08:06:24 +0000: new info: {
    build = 143301;
    format = "app bundle with Mach-O thin (x86_64)";
    identifier = "com.github.xor-gate.syncthing-macosx";
    requirements = "designated => identifier \"com.github.xor-gate.syncthing-macosx\" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = JUW2CNK88G\n";
    "signing-time" = "2017-08-03 00:43:58 +0000";
    teamid = JUW2CNK88G;
    version = "0.14.33-1";
}
2017-08-03 08:06:24 +0000: The update archive isn't signed with a DSA key, and the app is signed with a new Code Signing identity that doesn't match code signing of the original app: Error Domain=NSOSStatusErrorDomain Code=-67050 "(null)" UserInfo={SecCSArchitecture=x86_64}. At least one method of signature verification must be valid. The update will be rejected.

We need to write an update errata for old users.

ssbarnea commented 7 years ago

I am more than willing to donate some small amount to have a signed app on MacOS and I am sure others would be willing to. Without signing syncthing future would be kinda doomed as MacOS platform cannot be ignored.

PS. I know that I can build my own, but my life if too short to do that with all my tools, I would rather forget about the one that is not easy to install/use ;)

xor-gate commented 7 years ago

@ssbarnea last version is signed by @virusman developer account and should work without problems. Latest release breaks the auto-updater so it is not added as latest update-able release yet.