00
:
00
:
00
:
00
Corso SEO AI - Usa SEOEMAIL al checkout per il 30% di sconto

Firma e Notarizzazione

La firma del codice (code signing) e la notarizzazione sono necessarie per distribuire applicazioni Electron in modo professionale. Senza firma, gli utenti riceveranno avvisi di sicurezza dal sistema operativo.

Perché Firmare

  • Windows: Senza firma, SmartScreen mostra un avviso “Windows ha protetto il tuo PC”
  • macOS: Da macOS Catalina, le app non notarizzate non possono essere aperte
  • Fiducia: La firma garantisce che l’app non è stata manomessa dopo la distribuzione
  • Auto-update: Gli aggiornamenti automatici richiedono la firma su macOS

Firma su Windows

Ottenere un Certificato

Per firmare su Windows hai bisogno di un certificato di code signing. Puoi acquistarlo da autorità di certificazione come DigiCert, Sectigo o GlobalSign.

Configurazione con electron-builder

# electron-builder.yml
win:
  target: nsis
  signingHashAlgorithms:
    - sha256
  certificateFile: ./cert/certificate.pfx
  certificatePassword: ${WIN_CSC_KEY_PASSWORD}

Oppure tramite variabili d’ambiente:

# Variabili d'ambiente per la firma Windows
export WIN_CSC_LINK=./cert/certificate.pfx
export WIN_CSC_KEY_PASSWORD=la-tua-password

Firma con Electron Forge

// forge.config.js
module.exports = {
  packagerConfig: {
    windowsSign: {
      certificateFile: './cert/certificate.pfx',
      certificatePassword: process.env.WIN_CSC_KEY_PASSWORD,
    },
  },
};

Firma e Notarizzazione su macOS

Prerequisiti

  1. Un Apple Developer Account ($99/anno)
  2. Un certificato Developer ID Application da Apple
  3. Un App-Specific Password per la notarizzazione

Configurazione con electron-builder

# electron-builder.yml
mac:
  target:
    - dmg
    - zip
  identity: "Developer ID Application: Tuo Nome (TEAM_ID)"
  hardenedRuntime: true
  gatekeeperAssess: false
  entitlements: entitlements.mac.plist
  entitlementsInherit: entitlements.mac.plist

afterSign: scripts/notarize.js

File Entitlements

<!-- entitlements.mac.plist -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>com.apple.security.cs.allow-jit</key>
  <true/>
  <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
  <true/>
  <key>com.apple.security.cs.allow-dyld-environment-variables</key>
  <true/>
</dict>
</plist>

Script di Notarizzazione

// scripts/notarize.js
const { notarize } = require('@electron/notarize');

exports.default = async function notarizing(context) {
  const { electronPlatformName, appOutDir } = context;

  if (electronPlatformName !== 'darwin') return;

  const appName = context.packager.appInfo.productFilename;

  console.log('Notarizzazione in corso...');

  await notarize({
    appBundleId: 'com.example.miaapp',
    appPath: `${appOutDir}/${appName}.app`,
    appleId: process.env.APPLE_ID,
    appleIdPassword: process.env.APPLE_ID_PASSWORD,
    teamId: process.env.APPLE_TEAM_ID,
  });

  console.log('Notarizzazione completata!');
};

Variabili d’Ambiente per macOS

export APPLE_ID=tuo@email.com
export APPLE_ID_PASSWORD=app-specific-password
export APPLE_TEAM_ID=ABCD123456

Firma con Electron Forge (macOS)

// forge.config.js
module.exports = {
  packagerConfig: {
    osxSign: {
      identity: 'Developer ID Application: Tuo Nome (TEAM_ID)',
      hardenedRuntime: true,
      entitlements: 'entitlements.mac.plist',
      'entitlements-inherit': 'entitlements.mac.plist',
    },
    osxNotarize: {
      appleId: process.env.APPLE_ID,
      appleIdPassword: process.env.APPLE_ID_PASSWORD,
      teamId: process.env.APPLE_TEAM_ID,
    },
  },
};

CI/CD con GitHub Actions

# .github/workflows/build.yml
name: Build & Release

on:
  push:
    tags: ['v*']

jobs:
  build-windows:
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npx electron-builder --win --publish always
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          WIN_CSC_LINK: ${{ secrets.WIN_CSC_LINK }}
          WIN_CSC_KEY_PASSWORD: ${{ secrets.WIN_CSC_KEY_PASSWORD }}

  build-macos:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npx electron-builder --mac --publish always
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          APPLE_ID: ${{ secrets.APPLE_ID }}
          APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
          APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
          CSC_LINK: ${{ secrets.MAC_CSC_LINK }}
          CSC_KEY_PASSWORD: ${{ secrets.MAC_CSC_KEY_PASSWORD }}

  build-linux:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npx electron-builder --linux --publish always
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Best Practice

  1. Non includere i certificati nel repository — usa variabili d’ambiente o secret management
  2. Automatizza la firma nella CI/CD — evita errori manuali
  3. Testa le build firmate — verifica che la firma e la notarizzazione funzionino correttamente
  4. Rinnova i certificati prima della scadenza — le app firmate con certificati scaduti non funzionano
  5. Usa hardened runtime su macOS — è obbligatorio per la notarizzazione