Integrated code signing for Windows and macOS with certificate management, timestamping, and validation. Supports various certificate sources including files, certificate stores, hardware security modules, and cloud signing services.
Comprehensive Windows code signing with multiple certificate source support.
/**
* Windows code signing configuration
*/
interface WindowsSignOptions {
/** Certificate file path (.p12/.pfx) */
certificateFile?: string | null;
/** Certificate password */
certificatePassword?: string | null;
/** Certificate SHA1 thumbprint (for store certificates) */
certificateSha1?: string | null;
/** Certificate subject name (for store certificates) */
certificateSubjectName?: string | null;
/** Additional signtool.exe options */
signtoolOptions?: Array<string> | null;
/** RFC 3161 timestamp server URL */
rfc3161TimeStampServer?: string | null;
/** Legacy timestamp server URL */
timeStampServer?: string | null;
/** Additional certificate file for cross-signing */
additionalCertificateFile?: string | null;
}
/**
* Custom Windows signing function
*/
interface CustomWindowsSign {
(configuration: CustomWindowsSignTaskConfiguration, packager: WinPackager): Promise<any>;
}
/**
* Custom Windows signing task configuration
*/
interface CustomWindowsSignTaskConfiguration {
/** File path to sign */
path: string;
/** Windows packager instance */
packager: WinPackager;
/** Hash of the file */
hash: string;
/** Signing options */
options: WindowsSignOptions;
}Usage Examples:
import { WindowsSignOptions, CustomWindowsSign } from "electron-builder";
// Certificate file signing
const fileSignOptions: WindowsSignOptions = {
certificateFile: "certificates/code-signing.p12",
certificatePassword: process.env.WINDOWS_CERT_PASSWORD,
rfc3161TimeStampServer: "http://timestamp.digicert.com",
signtoolOptions: ["/fd", "sha256", "/tr", "http://timestamp.digicert.com", "/td", "sha256"]
};
// Certificate store signing
const storeSignOptions: WindowsSignOptions = {
certificateSubjectName: "My Company, Inc.",
rfc3161TimeStampServer: "http://timestamp.digicert.com"
};
// Certificate thumbprint signing
const thumbprintSignOptions: WindowsSignOptions = {
certificateSha1: "1234567890ABCDEF1234567890ABCDEF12345678",
rfc3161TimeStampServer: "http://timestamp.digicert.com"
};
// Custom signing for Azure Key Vault, HSM, etc.
const customSign: CustomWindowsSign = async (configuration, packager) => {
console.log(`Custom signing ${configuration.path}`);
// Example: Azure SignTool signing
const { spawn } = require("child_process");
await new Promise((resolve, reject) => {
const process = spawn("AzureSignTool", [
"sign",
"-kvu", process.env.AZURE_KEY_VAULT_URL,
"-kvi", process.env.AZURE_CLIENT_ID,
"-kvs", process.env.AZURE_CLIENT_SECRET,
"-kvc", process.env.AZURE_CERT_NAME,
"-tr", "http://timestamp.digicert.com",
"-td", "sha256",
configuration.path
]);
process.on("close", (code) => {
if (code === 0) resolve(undefined);
else reject(new Error(`Signing failed with code ${code}`));
});
});
};
const config = {
win: {
sign: customSign, // or fileSignOptions for standard signing
publisherName: "My Company, Inc."
}
};Support for Windows certificate store and hardware security modules.
/**
* Certificate from Windows certificate store
*/
interface CertificateFromStoreInfo {
/** Certificate thumbprint (SHA1) */
thumbprint: string;
/** Certificate subject name */
subject?: string;
/** Certificate store name */
store?: string;
/** Machine vs user store */
isLocalMachine?: boolean;
}
/**
* File-based code signing information
*/
interface FileCodeSigningInfo {
/** Certificate file path */
file: string;
/** Certificate password */
password?: string;
}
/**
* Windows signing task configuration variants
*/
interface WindowsSignTaskConfiguration {
/** Certificate file information */
file?: FileCodeSigningInfo;
/** Certificate store information */
certificateFromStore?: CertificateFromStoreInfo;
/** Additional signing options */
options?: WindowsSignOptions;
}macOS code signing with identity management and notarization support.
/**
* Custom macOS signing function
*/
interface CustomMacSign {
(configuration: CustomMacSignOptions, packager: MacPackager): Promise<any>;
}
/**
* Custom macOS signing configuration
*/
interface CustomMacSignOptions {
/** Application path to sign */
appPath: string;
/** macOS packager instance */
packager: MacPackager;
/** Signing identity */
identity: string | null;
/** Entitlements plist file */
entitlements?: string | null;
/** Additional signing options */
options: any;
/** Platform (mas, mac, etc.) */
platform: string;
}Usage Examples:
import { CustomMacSign, MacConfiguration } from "electron-builder";
// Standard macOS signing
const macConfig: MacConfiguration = {
identity: "Developer ID Application: My Company (TEAM123456)",
entitlements: "build/entitlements.plist",
entitlementsInherit: "build/entitlements.inherit.plist",
gatekeeperAssess: false,
hardenedRuntime: true,
darkModeSupport: true
};
// Custom macOS signing
const customMacSign: CustomMacSign = async (configuration, packager) => {
console.log(`Signing ${configuration.appPath} with ${configuration.identity}`);
// Custom signing logic
const { exec } = require("child_process");
const { promisify } = require("util");
const execAsync = promisify(exec);
await execAsync(`codesign --force --deep --sign "${configuration.identity}" "${configuration.appPath}"`);
// Verify signature
await execAsync(`codesign --verify --deep --strict "${configuration.appPath}"`);
};
const config = {
mac: {
sign: customMacSign,
identity: "Developer ID Application: My Company (TEAM123456)",
entitlements: "build/entitlements.plist"
}
};Standard environment variables for code signing configuration:
Windows:
WINDOWS_CERT_PASSWORD - Certificate passwordCSC_LINK - Certificate file pathCSC_KEY_PASSWORD - Certificate passwordWIN_CSC_LINK - Windows-specific certificate pathWIN_CSC_KEY_PASSWORD - Windows-specific certificate passwordmacOS:
CSC_LINK - Certificate file path (.p12)CSC_KEY_PASSWORD - Certificate passwordCSC_NAME - Certificate name/identityAPPLE_ID - Apple ID for notarizationAPPLE_ID_PASSWORD - Apple ID passwordAPPLE_TEAM_ID - Apple Team IDUsage Examples:
# Windows environment setup
export WINDOWS_CERT_PASSWORD="my-cert-password"
export CSC_LINK="certificates/windows-cert.p12"
# macOS environment setup
export CSC_LINK="certificates/mac-cert.p12"
export CSC_KEY_PASSWORD="my-cert-password"
export APPLE_ID="developer@company.com"
export APPLE_ID_PASSWORD="app-specific-password"
export APPLE_TEAM_ID="TEAM123456"
# Build with signing
npm run buildApple notarization for distribution outside the Mac App Store.
/**
* Notarization is automatically attempted when:
* - Building for distribution (not development)
* - Code signing identity is Developer ID
* - Required environment variables are present
*/
// Notarization environment variables
const notarizationEnv = {
APPLE_ID: "developer@company.com",
APPLE_ID_PASSWORD: "app-specific-password", // Use app-specific password
APPLE_TEAM_ID: "TEAM123456"
};
// Alternative: Keychain-based notarization
const keychainNotarization = {
APPLE_ID: "developer@company.com",
APPLE_ID_PASSWORD: "@keychain:AC_PASSWORD", // Reference keychain item
APPLE_TEAM_ID: "TEAM123456"
};Setup for CI/CD:
# GitHub Actions example
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
CSC_LINK: ${{ secrets.MAC_CERT_BASE64 }}
CSC_KEY_PASSWORD: ${{ secrets.MAC_CERT_PASSWORD }}Built-in validation and verification of signed applications.
/**
* Code signing validation occurs automatically:
* - Before packaging (pre-flight checks)
* - After signing (verification)
* - During notarization (macOS)
*/
// Windows validation
const windowsValidation = {
// Verifies signature using signtool
verifySignature: true,
// Checks timestamp validity
checkTimestamp: true,
// Validates certificate chain
validateChain: true
};
// macOS validation
const macValidation = {
// Verifies code signature
gatekeeperAssess: false, // Skip during build
// Validates entitlements
strictVerify: true,
// Checks hardening
hardenedRuntime: true
};Best practices for certificate storage and management.
Windows Certificate Storage:
// Certificate file (development)
const devConfig = {
win: {
certificateFile: "certs/dev-cert.p12",
certificatePassword: process.env.DEV_CERT_PASSWORD
}
};
// Certificate store (production)
const prodConfig = {
win: {
certificateSubjectName: "My Company, Inc.",
// Certificate must be installed in Windows certificate store
}
};
// Hardware Security Module (HSM)
const hsmConfig = {
win: {
sign: async (configuration, packager) => {
// Custom HSM signing logic
await signWithHSM(configuration.path);
}
}
};macOS Certificate Storage:
// Certificate file
const fileConfig = {
mac: {
identity: "Developer ID Application: My Company (TEAM123456)"
// Certificate .p12 file via environment: CSC_LINK
}
};
// Keychain certificate
const keychainConfig = {
mac: {
identity: "My Company", // Keychain will find matching certificate
}
};Common code signing issues and solutions:
Windows:
macOS:
Usage Examples:
// Debug signing issues
const debugConfig = {
win: {
sign: async (configuration, packager) => {
console.log("Signing file:", configuration.path);
console.log("Certificate info:", configuration.options);
try {
await packager.sign(configuration.path, configuration.options);
console.log("Signing successful");
} catch (error) {
console.error("Signing failed:", error.message);
throw error;
}
}
},
mac: {
identity: process.env.MAC_IDENTITY,
// Enable verbose logging
extendInfo: {
ElectronAsarIntegrity: false // Disable for debugging
}
}
};Code signing provides essential security and trust for distributed applications, ensuring users can verify the authenticity and integrity of your software across Windows and macOS platforms.