Electron Code Signing: Using SSL.com codeSignTool for EV code signing
Tags: electron, forge, sslcom
Published: 2024-05-09 14:23:41

Once you have purchased the EV Code Signing Certificate from SSL.com, you can then use the codeSignTool offered by them for doing application code signing. Based on what I've tested, for signing a Windows app with [CodeSignTool-v1.2.7-windows](https://www.ssl.com/downloads/), it would work on a Windows Machine. Unfortunately, I failed to get their unix codeSignTool to work on a Mac machine.

The app that I'm signing is an Electron App, with Forge (v7.4.0) configured to sign the Windows App during postMake. Hence, Forge's postMake hook was used in this example.

In your windows machine, run `electron-forge make` command so that MakerSquirrel can generate the .exe for signing during post hook.
```javascript
const config: ForgeConfig = {
  packagerConfig: {
    asar: true,
    icon: './build/icon',
    name: 'My App',
    appBundleId: 'com.myApp.electron',
    usageDescription: {
      Camera:
        'App requires access to your camera for complete experience.',
    },
  },
  rebuildConfig: {},
  makers: [
    new MakerSquirrel((arch) => ({
      // Make sure app name without space, see @https://github.com/electron/forge/issues/3462
      name: appName.replace(' ', '-'),
      authors: 'Myself Inc',
      description: 'My Desktop app'
    })),
  ],
  hooks: {
    postMake: async (config, makeResults) => {
      if (process.platform === 'darwin') {
        return makeResults;
      } else {
        // Window machine runs this block
        makeResults.map((result) => {
          const TEMP_DIR = path.join(__dirname, 'release', 'temp');
          if (!fs.existsSync(TEMP_DIR)) {
            fs.mkdirSync(TEMP_DIR, { recursive: true });
          }

          result.artifacts.forEach((artifact) => {
            if (artifact.endsWith('.exe')) {
              console.log('===> Signing', artifact);
              const { name, dir } = path.parse(artifact);
              // CodeSignTool can't sign in place without verifying the overwrite with a
              // y/m interaction so we are creating a new file in a temp directory and
              // then replacing the original file with the signed file.
              const tempFile = path.join(TEMP_DIR, name);
              const setDir = `cd ./CodeSignTool/CodeSignTool-v1.2.7-windows`; // depending on where your codeSignTool is located
              const signFile = `CodeSignTool sign -input_file_path="${artifact}" -output_dir_path="${TEMP_DIR}" -credential_id="${process.env.WIN_SIGN_CREDENTIAL_ID}" -username="${process.env.WIN_SIGN_USERNAME}" -password="${process.env.WIN_SIGN_PASSWORD}" -totp_secret="${process.env.WIN_SIGN_TOTP}"`;
              const moveFile = `mv "${tempFile}" "${dir}"`;
              childProcess.execSync(`${setDir} && ${signFile} && ${moveFile}`, {
                stdio: 'inherit',
              });
            }
          });
          return result;
        });
        return makeResults;
      }
    }
  }
};
```

Note that `WIN_SIGN_CREDENTIAL_ID`, `WIN_SIGN_USERNAME`, `WIN_SIGN_PASSWORD`, and `WIN_SIGN_TOTP` shall be obtained from SSL.com, get the authorized signer from your organization account to give them to you. Have fun!