Whether you're a developer configuring HTTPS for your web server or shipping an Android app to the Play Store, you're relying on the same underlying concept: digital signatures. This post walks through how signing works from first principles, then shows how it plays out in three real-world scenarios — web SSL, Android app signing, and iOS app signing.
The Basics: What Is a Digital Signature?
The goal of signing is to verify integrity — proving that a piece of data hasn't been tampered with and that it genuinely came from who it claims to.
Here's how it works:
- The sender computes a cryptographic hash (also called a digest) of the original data. This is a fixed-length fingerprint of the content.
- The sender encrypts that hash with their private key. The result is the digital signature.
- The sender transmits the original data along with the signature.
On the receiving end, verification is straightforward:
decrypt(signature, public_key) → digest₁
hash(original_data) → digest₂
If digest₁ == digest₂, the data is authentic and unmodified.
This works because:
- Only the holder of the private key could have produced that signature.
- Any modification to the data would produce a completely different hash, breaking the comparison.
Note: In practice, the hash is not "encrypted" in the traditional sense — it is signed using asymmetric cryptography (e.g., RSA or ECDSA). The distinction matters: signing with a private key is the inverse operation of verification with a public key, and it doesn't provide confidentiality, only authenticity.
Part 1: SSL/TLS Certificates for HTTPS
What Is an SSL Certificate?
An SSL certificate is essentially a digitally signed identity card for a website. Before it is signed, it exists as a Certificate Signing Request (CSR) — a file you generate on your server that contains:
- Your public key (generated as part of an RSA or ECDSA key pair; the private key stays on your server)
- Identifying metadata: domain name, organization name, location, country, and expiry date
You submit the CSR to a Certificate Authority (CA) — a trusted third party like Let's Encrypt, DigiCert, or Sectigo. The CA verifies your identity, then:
- Computes a hash of the certificate data (your public key + metadata)
- Signs that hash with the CA's own private key
- Returns the signed certificate to you
The final certificate you install on your server contains:
SSL Certificate = (Metadata including your public key) + Hash + Signature (encrypted with CA's private key)
Files on Your Server
| File | Purpose |
|---|---|
.crt / .cer / .pem |
The signed certificate, sent to browsers during the TLS handshake |
.key / .pem (private key) |
Your server's private key — never shared, stored securely on disk |
In Nginx, for example, you reference both files in your config:
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
The TLS Handshake: How Your Browser Verifies the Certificate
When you visit an HTTPS site, your browser:
- Downloads the signed certificate from the web server.
- Verifies the signature using the CA's public key, which is pre-installed in your OS or browser as a trusted root:
- Decrypts the signature with the CA's public key →
digest₁ - Hashes the readable certificate data →
digest₂ - Checks that
digest₁ == digest₂
- Decrypts the signature with the CA's public key →
- If the signature is valid, the browser trusts the website's public key embedded in the certificate.
- The browser then uses that public key to initiate a key exchange (e.g., via Diffie-Hellman or by encrypting a pre-master secret). Both sides derive a shared symmetric session key, which is used to encrypt all further communication.
The website's public key is completely visible in the certificate — unencrypted, by design. Public keys are meant to be public. The trust comes from the fact that the CA's signature vouches for whose public key it is.
The Trust Anchor in HTTPS
The whole system rests on CA root certificates pre-installed in your operating system or browser. These are the trust anchors — if you trust the CA, and the CA has signed the certificate, then you transitively trust the website's identity.
Part 2: Android App Signing
How It Differs from SSL
Android app signing uses the same cryptographic primitives — RSA or ECDSA key pairs, hashing, and signatures — but with one key difference: you sign your own certificate with your own private key, rather than having a CA sign it.
This is called a self-signed certificate. There's no CA involved. The certificate inside an Android APK or App Bundle looks like this:
App Signing Certificate = (Metadata including your public key) + Hash + Signature (signed with your own private key)
What Android Signs
When you build a release APK or App Bundle, your build tooling:
- Computes a hash of the app's contents (code, resources, manifest, etc.)
- Signs that hash with your developer private key (stored in a
.jksor.keystorefile, or managed by Google Play App Signing) - Packages the certificate alongside the app
How Android Verifies and Establishes Trust
Android doesn't rely on a CA for app trust — it uses first-install trust pinning:
- First install: The user installs the app. Android extracts the developer's public key from the certificate embedded in the APK and stores it.
- Subsequent updates: When an update arrives, Android retrieves the stored public key and uses it to validate the signature on the new APK.
- If the signatures don't match (e.g., someone else signed the update), Android rejects the update.
This means only the original developer — whoever holds the original private key — can ship updates to an installed app. A malicious actor can't push a spoofed update, even if they publish an app with the same package name.
Google Play App Signing: Google offers an optional (and for new apps, mandatory) service where Google holds a copy of your app signing key. You upload your APK signed with an "upload key," Google re-signs it with your app signing key before delivering it to users. This protects you from losing your key.
Trust Anchor in Android App Signing
Unlike HTTPS, the trust anchor here is not a CA. It is:
- On first install: Trust is bootstrapped from the APK itself (or from the Play Store's verification layer, if distributed through Play)
- On updates: The trust anchor is the public key stored from the previous installation
Part 3: iOS App Signing
Overview
iOS app signing is more centralized than Android. Apple acts as a mandatory CA — you cannot install an app on a non-jailbroken device unless Apple has signed off on it.
Key Concepts
| Concept | Description |
|---|---|
| Apple Root CA | Pre-installed on every iOS device; the ultimate trust anchor |
| Developer Certificate | Issued by Apple after you enroll in the Apple Developer Program; signed by Apple's CA |
| Provisioning Profile | A file that binds your app ID, device UDIDs (for development), and your developer certificate together |
| App ID | A unique identifier for your app (e.g., com.yourcompany.yourapp) |
The Signing Process
- You generate a Certificate Signing Request (CSR) on your Mac (via Keychain Access).
- You submit the CSR to Apple through the Developer Portal. Apple signs it with their intermediate CA, producing your developer certificate.
- In Xcode, you select your certificate and provisioning profile. When you build and archive your app, Xcode:
- Hashes the app bundle
- Signs it with your developer private key
- The resulting
.ipa(app package) contains both your app and the provisioning profile.
Verification on Device
When a user installs an app (via the App Store or TestFlight):
- iOS verifies that your developer certificate was signed by Apple — using Apple's root CA already trusted on the device.
- iOS verifies that the app bundle's signature is valid using your developer certificate's public key.
- For App Store apps, Apple additionally re-signs the app with an Apple Distribution Certificate before delivery, adding another layer of verification.
This two-layer verification means:
- Apple vouches for you (via your developer certificate)
- You vouch for your app (via your app signature)
Trust Anchor in iOS
The trust anchor is Apple's Root CA, pre-installed on every iOS device. This is similar in spirit to the HTTPS model — a central authority whose public key is universally trusted on the platform.
For ad-hoc or enterprise distribution (outside the App Store), users must explicitly trust the developer certificate in Settings, because Apple hasn't publicly vouched for it via the App Store review process.
Summary: Comparing the Three Models
| HTTPS / SSL | Android App Signing | iOS App Signing | |
|---|---|---|---|
| Who signs? | Certificate Authority (CA) | Developer (self-signed) | Developer + Apple |
| Trust anchor | CA root certificate (in OS/browser) | Public key from first install | Apple Root CA (on device) |
| Certificate type | CA-signed certificate | Self-signed certificate | Apple-issued developer certificate |
| Update trust | Re-verified per connection | Pinned to first-install key | Verified against Apple CA |
| Central authority required? | Yes (CA) | No | Yes (Apple) |
Key Takeaways
- Signing is always about integrity and authenticity — proving data came from a specific source and hasn't been tampered with.
- The trust model differs between platforms: HTTPS and iOS rely on centralized CAs, while Android bootstraps trust from the first installation.
- Your private key is everything — losing it means losing the ability to issue updates (Android) or sign new builds (iOS). Protect it accordingly.
- Public keys are public — sharing them is the whole point; the security comes from the fact that only you hold the corresponding private key.
