Sign inSign up

bruienne/pkgsign

By bruienne

Updated almost 10 years ago

Sign flat Apple installer packages

Image
3

390

bruienne/pkgsign repository overview

Introduction

Based on signing instructions as found in the XAR fork by Rob Braun: https://mackyle.github.io/xar/howtosign.html#howto

Github repo for the source project: https://github.com/mackyle/xar

Preparation

You will need a valid installer codesign certificate and private key from the Apple Developer site:

https://developer.apple.com/account/ios/certificate/

Be sure to pick the right installer signing certificate for your purposes:

A Mac Installer Distribution certificate is valid for Mac App Store submission. A Developer ID Installer certificate is valid for distribution outside the Mac App Store.

The tool will print the type of certificate used in its output:

Cert extended key usage 1.2.840.113635.100.4.9 - MAS Installer or Cert extended key usage 1.2.840.113635.100.4.13 - Non-MAS Installer

Usage

To invoke with an unsigned package:

$ docker run -it --rm -v /path/to/my.pkg:/work/my.pkg -v /path/to/sign.cer:/work/sign-cert.cer -v /path/to/sign-key.pem:/work/sign.pem bruienne/pkgsign

By default the tool will log all its actions to stdout. If that's undesired, invoke with the -q flag instead:

$ docker run -it --rm -v /path/to/my.pkg:/work/my.pkg -v /path/to/sign.cer:/work/sign-cert.cer -v /path/to/sign-key.pem:/work/sign.pem bruienne/pkgsign /run.sh -q

After a successful run the package my.pkg should be signed. To check signing status the following tools may be of use:

pkgutil - Included with a standard OS install Suspicious Package - http://www.mothersruin.com/software/SuspiciousPackage/ Pacifist - https://www.charlessoft.com/ Signature Check - http://adcdownload.apple.com/Developer_Tools/signaturecheck/signaturecheck.dmg (Dev portal)

Checking with pkgutil
$ /usr/sbin/pkgutil --check-signature MySignedPackage.pkg
Package "MySignedPackage.pkg":
   Status: signed by a developer certificate issued by Apple
   Certificate Chain:
    1. 3rd Party Mac Developer Installer: John Doe (WJ1C234G56)
       SHA1 fingerprint: 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF 12 34 56 78 90
       -----------------------------------------------------------------------------
    2. Apple Worldwide Developer Relations Certification Authority
       SHA1 fingerprint: FF 67 97 79 3A 3C D7 98 DC 5B 2A BE F5 6F 73 ED C9 F8 3A 64
       -----------------------------------------------------------------------------
    3. Apple Root CA
       SHA1 fingerprint: 61 1E 5B 66 2C 59 3A 08 FF 58 D1 4A E2 24 52 D1 98 DF 6C 60
Verifying Gatekeeper status
$ spctl -a -v --type install MySignedPackage.pkg  
MySignedPackage.pkg: accepted
source=Developer ID

Source files

The Dockerfile:

FROM ubuntu
MAINTAINER [email protected]

RUN apt-get update
RUN apt-get install -y build-essential git autoconf libxml2-dev libcurl4-openssl-dev python2.7 libbz2-dev liblzma-dev libssl-dev
RUN git clone https://github.com/mackyle/xar.git
RUN cd xar/xar && \
    ./autogen.sh && \
    ./configure --with-bzip2 --with-lzma=/usr && \
    make && \
    make install

RUN mkdir /work

COPY sign-pkg.sh /run.sh
COPY wwdr.cer /work/wwdr.cer
COPY appleca.cer /work/appleca.cer

RUN chmod +x /run.sh

WORKDIR /work

CMD /run.sh

The script that does the work:

#!/bin/bash
#
# Sign Apple pkgs using xar and openssl
#

QUIET=$1

log () {
  if [[ $QUIET != "-q" ]]; then
    echo "$1"
  fi
}

PKG_IN="$(ls /work/*.pkg)"
SIGNING_CERT="/work/sign.cer"
SIGNING_KEY="/work/sign.pem"

log "Package to sign: $PKG_IN"
log "Signing cert: $SIGNING_CERT"
log "Signing key: $SIGNING_KEY"

# Does the PKG file exist?
if [[ ! -e $PKG_IN ]]; then
  log "Source pkg not found, quiting."
  exit 1
fi

# Is the PKG file a compatible XAR archive?
if [[ $(file $PKG_IN | grep xar | wc -c) -eq 0 ]]; then
  log "Source pkg not a valid xar archive, quiting."
  exit 1
fi

# Does the signing cert exist?
if [[ ! -e $SIGNING_CERT ]]; then
  log "Signing cert not found, quiting."
  exit 1
fi

# Is this a proper Apple code-signing cert?
extended_key_usage_oid=$(openssl x509 -inform der -in $SIGNING_CERT -text -noout | awk -F. '/1.2.840.113635.100.4/{print $7}')

if [[ $extended_key_usage_oid -eq 9 ]]; then
  log "Cert extended key usage 1.2.840.113635.100.4.9 - MAS Installer"
elif [[ extended_key_usage_oid -eq 13 ]]; then
  log "Cert extended key usage 1.2.840.113635.100.4.13 - Non-MAS Installer"
else
  log "Signing cert is not a valid Apple code-signing cert, quiting."
  exit 1
fi

# Does the signing key exist?
if [[ ! -e $SIGNING_KEY ]]; then
  log "Signing key not found, quiting."
  exit 1
fi

# Is the signing key valid?
if [[ $(openssl rsa -in $SIGNING_KEY -check -noout) != "RSA key ok" ]]; then
  log "Signing key not a valid RSA key, quiting."
  exit 1
fi

# Do the signing cert and key match?
sign_cert_hash=$(openssl x509 -inform der -noout -modulus -in $SIGNING_CERT | md5sum | awk '{print $1}')
sign_key_hash=$(openssl rsa -noout -modulus -in $SIGNING_KEY | md5sum | awk '{print $1}')

if [[ $sign_cert_hash != $sign_key_hash ]]; then
  log "Signing cert and key do not match, quiting."
  exit 1
fi

# Determine length of signature to reserve space in pkg toc
log "Getting signature length..."
sig_length=$(: | openssl dgst -sign $SIGNING_KEY -binary | wc -c)
log "Signature length is ${sig_length}"

# Check whether this pkg is already signed, assume we're replacing the signature
#  if it is.
if [[ $(xar --extract-sig pkgcerts.cer -f $PKG_IN 2>&1 | wc -c) -gt 0 ]]; then
  log "Signing unsigned package..."
  SIGN_METHOD="--sign"
else
  log "Replacing signature on already signed package..."
  SIGN_METHOD="--replace-sign"
fi

# Insert certs into pkg, get digest info to sign
log "Inserting certs and creating digest to sign..."
xar $SIGN_METHOD -f $PKG_IN --digestinfo-to-sign digestinfo.dat \
  --sig-size $sig_length \
  --cert-loc $SIGNING_CERT --cert-loc wwdr.cer --cert-loc appleca.cer

# Create RSA signature
log "Creating RSA signature..."
openssl rsautl -sign -inkey $SIGNING_KEY -in digestinfo.dat -out signature.dat

# Insert the RSA signature into the pkg
log "Inserting RSA signature into the pkg..."
xar --inject-sig signature.dat -f $PKG_IN

# Clean up, to be nice
log "Cleaning up..."
rm -f signature.dat digestinfo.dat sig.dat

log "Done, exiting."
exit 0

Tag summary

Content type

Image

Digest

Size

200.8 MB

Last updated

almost 10 years ago

docker pull bruienne/pkgsign