Thursday, February 18, 2021 [Tweets] [Favorites]

Code Signing When Building on Apple Silicon


codesign should choose the signing format based on the deployment target:

  • If your deployment target is 10.11 or later, you get sha256.
  • If your deployment target is earlier, you get both sha1 and sha256.

This problem crops up because, when building for both Intel and Apple Silicon, your deployment targets are different. You might set the deployment target to 10.9 but, on Apple Silicon, that’s raised to the minimum Apple Silicon system, 11.0. So, which deployment target does it choose?

The wrong one, if you’re trying to deploy to an older version of macOS. I’ve seen lots of posts about this problem in relation to installer packages, but it applies to apps, too.

The upshot is that you have problems if your deployment target is less than 10.11 and you sign on Apple Silicon. When you run on, say, macOS 10.10, the system looks for a sha1 hash, doesn’t find it, and complains.

You can work around this by setting OTHER_CODE_SIGN_FLAGS to --digest-algorithm=sha1,sha256.

Update (2021-02-19): Peter Ammon:

#fishshell was bitten by this, it means we can no longer use Apple’s tools to codesign, so we use xar instead.

See also: Jonathan Deutsch.


Be careful about conflating code-signing and package-signing: these are two entirely different beasts, and there are two distinct bugs here.

The code-signing bug is that the codesign tool looks at the deployment target of the *native* architecture (the one it's running on) to decide if a backward-compatible SHA-1 code directory should be added. If you run codesign on arm64, it will always see this as 11.*, even when signing the x86_64 slice. (Quinn's comment quoted above fails to account for the fact that code-signing is always a per-architecture thing: in a universal binary, each slice of the Mach-O is signed separately, so there is no reason that the x86_64 slice couldn't get a fallback SHA-1 code directory while the arm64 slice does not. Failing that, Michael's workaround using --digest-algorithm ought to suffice.)

According to the open-source version of the Security framework [see MachORep::prepareForSigning()], code-signing SHA-256 support was added in 10.11.4, so this bug would mostly impact Yosemite and earlier systems.

The package-signing bug appears to be that the CMSEncoder (also in the Security framework, and used by productsign) has changed in Big Sur so that the SignerInfo's SignatureAlgorithmIdentifier (c.f. RFC 5652, ยง10.1.2) is now SHA1-with-RSA (1.2.840.113549.1.1.5) instead of RSA-encryption (1.2.840.113549.1.1.1) as before. I don't claim to understand the difference, but it does appear that on the CMSDecoder side, modern versions of the Security framework (10.12 and newer?) are able to deal with either, but 10.11 and older versions stumble over the newer SHA1-with-RSA algorithm type.

The reason that the approach used by fish-shell works is only because it avoids CMS-style signing altogether. CMS-style signatures were added to packages in 10.8, and were always an optional-but-preferred signature style (preferred, because they support trusted timestamps). For backward-compatibility reasons, the macOS Installer will always fall back on the old "RSA-style" signature if the CMS one isn't there. The "use xar instead" approach is creating only the RSA-style signature, so avoids the CMS issues altogether. (The optional CMS signature scheme [x-signature in the XML xar TOC] is an Apple-only extension to xar that isn't in other xar versions, outside of the one on

(By the way, code-signing is also based on CMSEncoder/CMSDecoder, but the change that bites productsign doesn't seem to effect the backward compatibility of code signatures [once you hack past the deployment target bug] because code-signing explicitly specifies a SHA-256 signer algorithm [see SecCodeSigner::Signer::signCodeDirectory()], and even though Big Sur CMSEncoder does switch the SignatureAlgorithmIdentifier here too [to SHA256-with-RSA], it doesn't seem to cause the same problems in 10.11's CMSDecoder that I can see.)

Apologies for this long, tedious explanation. I'm not sure *why* I spent time tracking all this down, but since I did, maybe someone else can benefit!

@Randy Thanks! BTW, your Apparency app looks really cool.

Stay up-to-date by subscribing to the Comments RSS Feed for this post.

Leave a Comment