16

I have Windows application that can run on OS X under Wine. For convenience I want to pack the application as OS X app (ZIP archive of xxx.app folder based on WineBottler).

Note that the main executable of the app (as defined by CFBundleExecutable tag of Info.plist) is a shell script, not a binary.

I want to sign the application to pass through OS X Gatekeeper. As my complete build process runs on Windows (and as I actually do not have Mac at all) I need to sign it on Windows.

I already found that signing the app creates _CodeSignature folder with four files:

CodeDirectory
CodeRequirements
CodeResources
CodeSignature

I have not found any specification describing contents of these files.

Experimentally, I've found that CodeResources is an XML file with SHA-1 hashes of all files in the app. I can generate that.

The contents of CodeRequirements binary file seems to be fixed. It does not seem to change with contents of the app. Confirmation is appreciated. What is this file good for?

As for the binary files CodeDirectory and CodeSignature I have no clue.

Both files change with app contents. It seems that any app file change (including plain text license file) affects them.

The CodeSignature obviously contains the signature. I can see plain-text information about code signing certificate in the file. Is there any tool that can generate the file? As it is a signature, it should be pretty standard. Though there can be some additional binary metadata that can make generation more difficult. Does anyone know what does it specifically sign? I can imagine that it signs only CodeResources file as that describes all other files in the app. Or does it actually sign all the files in the app recursively?

Native OS X apps have CodeResources only. So there's actually no signature in _CodeSignature. I suppose it's because they have embedded signature in the main executable binary. Note that my [Windows] binary (though it's not directly referred to by Info.plist as mentioned above) is code-signed using Windows signtool.exe. Apparently OS X recognizes the signature even without the reference as codesign -d -vvv xxx.app output includes information about the certificate:

Executable=/Applications/WinSCP.app/Contents/MacOS/startwine
Identifier=WinSCP
Format=bundle with generic
CodeDirectory v=20100 size=135 flags=0x0(none) hashes=1+3 location=embedded
Hash type=sha1 size=20
CDHash=a1ef4f04b2c1b4b793788ce3ab9d7881528f3d95
Signature size=4867
Authority=Martin Prikryl
Authority=VeriSign Class 3 Code Signing 2010 CA
Authority=VeriSign Class 3 Public Primary Certification Authority - G5
Signed Time=23.4.2014 23:51:18
Info.plist entries=14
Sealed Resources version=2 rules=12 files=846
Internal requirements count=2 size=136

Confusing is that is does not mention binary name at all. Anyway, it does not make Gatekeeper happy. Note the the above test is run against app that already includes CodeResources file (that's probably what the Sealed Resources version refers too as rules and files counts match with the file contents).

15
  • Is the binary in Mach-O format?
    – trojanfoe
    Commented Apr 30, 2014 at 7:01
  • 1
    Did you read Apple's Code Signing Guide ( developer.apple.com/library/mac/documentation/security/… )? It answers at least some of your questions.
    – danielv
    Commented May 8, 2014 at 19:19
  • 1
    @danielv Thanks for the link. I've actually seen it before, but read it more carefully again now. It confirmed my assumption that CodeRequirements is not part of the signature as such and that I should be looking mainly at CodeDirectory and CodeSignature. Unfortunately there's no description of their structure. Commented May 9, 2014 at 7:02
  • 1
    By the way, the codesign utility and the codesigning library source code is open and available: opensource.apple.com/source/security_systemkeychain/… - opensource.apple.com/source/libsecurity_codesigning . It has been tried before but I don't think it was ever compiled on non Mac platforms. But you might find useful information there if you wade through the source code.
    – danielv
    Commented May 9, 2014 at 12:01
  • 1
    Check out isign, it is a python implementation of codesign
    – XMB5
    Commented Jul 18, 2018 at 1:24

2 Answers 2

9
+100

We have tried to reverse-engineer the code signing using source code of libsecurity_codesigning library. Although it seems feasible, it's still too much effort, so we consider giving up. We would like to at least share what we have found so far, so others may build upon.

We have found that when codesign does not find MachO binary, it falls back to "architecture agnostic" signing implemented in SecCodeSigner::Signer::signArchitectureAgnostic.

Key steps there:

  • CodeDirectory file generation. The directory includes few SHA-1 hashes of various pieces of the bundle in addition to file header (including directory version)
  • CodeSignature file generation. The signature signs CodeDirectory file using Cryptographic Message Syntax (CMS) format. The signature can be verified on any platform using OpenSSL:

    openssl cms -verify -in CodeSignature -inform DER
        -content CodeDirectory -noverify -out CodeDirectory.verified
    

    Note that -noverify is needed to skip certificate validation as OpenSSL does not seem to support "code signing" purpose of certificates.

    OpenSSL should be able to create CMS signature using following command:

    openssl cms -sign -in CodeDirectory -out CodeSignature 
        -signer certificate.pem -outform DER
    

    But such signature is not accepted by OS X.

We didn't get any further.

1
  • Hi, just wondering if you made some more progress in this area... I'm trying to build signature verifier to macho file on linux server using openssl.. verify the CMS signature chain is one thing, But I'm struggling to find out how to validate the file contents hash (what parts of the macho file goes to what hashes in CodeDirectory. perhaps do you know how to calculate them ? thanks !
    – Zohar81
    Commented Nov 28, 2018 at 8:32
3

Not strictly signing on Windows, but have you considered Remote Desktop into a friends Mac or renting a Mac in the Cloud? http://www.macincloud.com seems to have fairly reasonable plans.

Could save a lot of the trouble. All you really need access to is the codesign tool and the Terminal.

Edit: You will still need an Apple Developer account to sign the application - Gatekeeper only allows signatures from Apple-issued developer ID certificates.

2
  • Thanks for the suggestion. I was considering this approach too. Note that you do not need Apple-issued certificate. I was able to sign application using codesign even with VeriSign certificate I have for signing Windows 8 Store applications. Gatekeeper was happy too. Commented May 14, 2014 at 5:00
  • Has anyone successfully used MacinCloud for this purpose? I've just noticed that they have a 1$/hour prepaid plan which seems to be perfect for infrequent, short-time usages.
    – mstrap
    Commented Sep 15, 2016 at 7:14

Not the answer you're looking for? Browse other questions tagged or ask your own question.