diff --git a/.changeset/stale-deers-cheat.md b/.changeset/stale-deers-cheat.md new file mode 100644 index 0000000000..f29159303f --- /dev/null +++ b/.changeset/stale-deers-cheat.md @@ -0,0 +1,6 @@ +--- +"app-builder-lib": patch +"@electron-builder/test": patch +--- + +fix: allow CSC_LINK to have a mime-type prefix that is stripped when converting it to a p12 for signing diff --git a/packages/app-builder-lib/src/codeSign/codesign.ts b/packages/app-builder-lib/src/codeSign/codesign.ts index ca75722567..86cd1dbbd1 100644 --- a/packages/app-builder-lib/src/codeSign/codesign.ts +++ b/packages/app-builder-lib/src/codeSign/codesign.ts @@ -7,29 +7,28 @@ import { statOrNull } from "builder-util/out/fs" import { download } from "../binDownload" /** @private */ -export async function downloadCertificate(urlOrBase64: string, tmpDir: TmpDir, currentDir: string): Promise { - urlOrBase64 = urlOrBase64.trim() +export async function importCertificate(cscLink: string, tmpDir: TmpDir, currentDir: string): Promise { + cscLink = cscLink.trim() let file: string | null = null - if ((urlOrBase64.length > 3 && urlOrBase64[1] === ":") || urlOrBase64.startsWith("/") || urlOrBase64.startsWith(".")) { - file = urlOrBase64 - } else if (urlOrBase64.startsWith("file://")) { - file = urlOrBase64.substring("file://".length) - } else if (urlOrBase64.startsWith("~/")) { - file = path.join(homedir(), urlOrBase64.substring("~/".length)) + if ((cscLink.length > 3 && cscLink[1] === ":") || cscLink.startsWith("/") || cscLink.startsWith(".")) { + file = cscLink + } else if (cscLink.startsWith("file://")) { + file = cscLink.substring("file://".length) + } else if (cscLink.startsWith("~/")) { + file = path.join(homedir(), cscLink.substring("~/".length)) + } else if (cscLink.startsWith("https://")) { + const tempFile = await tmpDir.getTempFile({ suffix: ".p12" }) + await download(cscLink, tempFile) + return tempFile } else { - const isUrl = urlOrBase64.startsWith("https://") - if (isUrl || urlOrBase64.length > 2048 || urlOrBase64.endsWith("=")) { + const mimeType = /data:.*;base64,/.exec(cscLink)?.[0] + if (mimeType || cscLink.length > 2048 || cscLink.endsWith("=")) { const tempFile = await tmpDir.getTempFile({ suffix: ".p12" }) - if (isUrl) { - await download(urlOrBase64, tempFile) - } else { - await outputFile(tempFile, Buffer.from(urlOrBase64, "base64")) - } + await outputFile(tempFile, Buffer.from(cscLink.substring(mimeType?.length ?? 0), "base64")) return tempFile - } else { - file = urlOrBase64 } + file = cscLink } file = path.resolve(currentDir, file) diff --git a/packages/app-builder-lib/src/codeSign/macCodeSign.ts b/packages/app-builder-lib/src/codeSign/macCodeSign.ts index 4a2480cd64..fe6e1c2dc6 100644 --- a/packages/app-builder-lib/src/codeSign/macCodeSign.ts +++ b/packages/app-builder-lib/src/codeSign/macCodeSign.ts @@ -9,7 +9,7 @@ import { homedir, tmpdir } from "os" import * as path from "path" import { getTempName } from "temp-file" import { isAutoDiscoveryCodeSignIdentity } from "../util/flags" -import { downloadCertificate } from "./codesign" +import { importCertificate } from "./codesign" export const appleCertificatePrefixes = ["Developer ID Application:", "Developer ID Installer:", "3rd Party Mac Developer Application:", "3rd Party Mac Developer Installer:"] @@ -191,7 +191,7 @@ export async function createKeychain({ tmpDir, cscLink, cscKeyPassword, cscILink await Promise.all([ // we do not clear downloaded files - will be removed on tmpDir cleanup automatically. not a security issue since in any case data is available as env variables and protected by password. - BluebirdPromise.map(certLinks, (link, i) => downloadCertificate(link, tmpDir, currentDir).then(it => (certPaths[i] = it))), + BluebirdPromise.map(certLinks, (link, i) => importCertificate(link, tmpDir, currentDir).then(it => (certPaths[i] = it))), BluebirdPromise.mapSeries(securityCommands, it => exec("security", it)), ]) return await importCerts(keychainFile, certPaths, [cscKeyPassword, cscIKeyPassword].filter(it => it != null) as Array) diff --git a/packages/app-builder-lib/src/winPackager.ts b/packages/app-builder-lib/src/winPackager.ts index cb8aebb082..946a0d3571 100644 --- a/packages/app-builder-lib/src/winPackager.ts +++ b/packages/app-builder-lib/src/winPackager.ts @@ -7,7 +7,7 @@ import { readdir } from "fs/promises" import * as isCI from "is-ci" import { Lazy } from "lazy-val" import * as path from "path" -import { downloadCertificate } from "./codeSign/codesign" +import { importCertificate } from "./codeSign/codesign" import { CertificateFromStoreInfo, CertificateInfo, @@ -66,7 +66,7 @@ export class WinPackager extends PlatformPackager { } return ( - downloadCertificate(cscLink, this.info.tempDirManager, this.projectDir) + importCertificate(cscLink, this.info.tempDirManager, this.projectDir) // before then .catch(e => { if (e instanceof InvalidConfigurationError) { diff --git a/test/src/helpers/codeSignData.ts b/test/src/helpers/codeSignData.ts index 38dae73b1b..e3f63f44ca 100644 --- a/test/src/helpers/codeSignData.ts +++ b/test/src/helpers/codeSignData.ts @@ -4,4 +4,4 @@ export const CSC_LINK = // Generated with `electron-builder create-self-signed-cert -p ` // noinspection SpellCheckingInspection export const WIN_CSC_LINK = - "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" + "data:application/x-pkcs12;base64,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"