Skip to content

Commit

Permalink
feat: asar integrity (macos only for now)
Browse files Browse the repository at this point in the history
  • Loading branch information
develar committed Jun 2, 2017
1 parent 2fab4bf commit 3e28ae2
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 34 deletions.
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"private": true,
"license": "MIT",
"scripts": {
"compile": "ts-babel packages/electron-builder-http packages/electron-builder-core packages/electron-builder-util packages/electron-publish packages/electron-builder packages/electron-builder-squirrel-windows packages/electron-updater packages/electron-publisher-s3 test && node ./test/vendor/yarn.js schema",
"compile": "ts-babel packages/asar-integrity packages/electron-builder-http packages/electron-builder-core packages/electron-builder-util packages/electron-publish packages/electron-builder packages/electron-builder-squirrel-windows packages/electron-updater packages/electron-publisher-s3 test && node ./test/vendor/yarn.js schema",
"lint": "node test/out/helpers/lint.js",
"pretest": "node ./test/vendor/yarn.js compile && node ./test/vendor/yarn.js lint && node ./test/vendor/yarn.js lint-deps",
"lint-deps": "node ./test/out/helpers/checkDeps.js",
Expand All @@ -15,7 +15,7 @@
"whitespace": "whitespace 'src/**/*.ts'",
"docker-images": "docker/build.sh",
"test-deps-mac": "brew install rpm dpkg mono lzip gnu-tar graphicsmagick xz && brew install wine --without-x11",
"update-deps": "lerna exec -- npm-check-updates --reject 'electron-builder-http,electron-builder-util,electron-builder-core,electron-publish,electron-forge-maker-appimage,electron-forge-maker-nsis,electron-forge-maker-snap' -a",
"update-deps": "node ./packages/update-deps.js",
"set-versions": "node test/out/helpers/setVersions.js",
"npm-publish": "yarn set-versions && yarn compile && ./packages/npm-publish.sh && conventional-changelog -p angular -i CHANGELOG.md -s",
"schema": "typescript-json-schema packages/electron-builder/tsconfig.json Config --out packages/electron-builder/scheme.json --noExtraProps --useTypeOfKeyword --strictNullChecks --titles",
Expand All @@ -31,15 +31,15 @@
"ajv": "^5.1.5",
"ajv-keywords": "^2.1.0",
"archiver": "^1.3.0",
"aws-sdk": "^2.59.0",
"aws-sdk": "^2.61.0",
"bluebird-lst": "^1.0.2",
"chalk": "^1.1.3",
"chromium-pickle-js": "^0.2.0",
"cuint": "^0.2.2",
"debug": "^2.6.8",
"electron-download-tf": "4.3.1",
"electron-is-dev": "^0.1.2",
"electron-osx-sign": "0.4.5",
"electron-osx-sign": "0.4.6",
"fs-extra-p": "^4.3.0",
"hosted-git-info": "^2.4.2",
"ini": "^1.3.4",
Expand All @@ -66,10 +66,10 @@
},
"devDependencies": {
"@types/ini": "^1.3.29",
"@types/jest": "^19.2.3",
"@types/jest": "^19.2.4",
"@types/js-yaml": "^3.5.30",
"@types/node-forge": "^0.6.9",
"@types/source-map-support": "^0.2.28",
"@types/source-map-support": "^0.4.0",
"@types/xml2js": "^0.0.33",
"babel-plugin-array-includes": "^2.0.3",
"babel-plugin-transform-async-to-module-method": "^6.24.1",
Expand All @@ -90,7 +90,7 @@
"path-sort": "^0.1.0",
"source-map-support": "^0.4.15",
"ts-babel": "^3.0.1",
"tslint": "^5.3.2",
"tslint": "^5.4.2",
"typescript": "^2.3.4",
"whitespace": "^2.1.0",
"xml2js": "^0.4.17"
Expand Down
18 changes: 18 additions & 0 deletions packages/asar-integrity/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "asar-integrity",
"version": "0.0.0-semantic-release",
"main": "out/asarIntegrity.js",
"author": "Vladimir Krivosheev",
"license": "MIT",
"repository": "electron-userland/electron-builder",
"bugs": "https://github.com/electron-userland/electron-builder/issues",
"homepage": "https://github.com/electron-userland/electron-builder",
"files": [
"out"
],
"dependencies": {
"bluebird-lst": "^1.0.2",
"fs-extra-p": "^4.3.0"
},
"typings": "./out/asar-integrity.d.ts"
}
34 changes: 34 additions & 0 deletions packages/asar-integrity/src/asarIntegrity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import BluebirdPromise from "bluebird-lst"
import { createHash } from "crypto"
import { createReadStream } from "fs"
import { readdir } from "fs-extra-p"
import * as path from "path"

export async function computeData(resourcesPath: string): Promise<{ [key: string]: string; }> {
// sort to produce constant result
const names = (await readdir(resourcesPath)).filter(it => it.endsWith(".asar")).sort()
const checksums = await BluebirdPromise.map(names, it => hashFile(path.join(resourcesPath, it), "sha512"))

const result: { [key: string]: string; } = {}
for (let i = 0; i < names.length; i++) {
result[names[i]] = checksums[i]
}
return result
}

export function hashFile(file: string, algorithm: string) {
return new BluebirdPromise<string>((resolve, reject) => {
const hash = createHash(algorithm)
hash
.on("error", reject)
.setEncoding("hex")

createReadStream(file)
.on("error", reject)
.on("end", () => {
hash.end()
resolve(<string>hash.read())
})
.pipe(hash, {end: false})
})
}
10 changes: 10 additions & 0 deletions packages/asar-integrity/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "../tsconfig-base.json",
"compilerOptions": {
"outDir": "out"
},
"declaration": true,
"include": [
"src/**/*.ts"
]
}
5 changes: 3 additions & 2 deletions packages/electron-builder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"electron-builder-http": "0.0.0-semantic-release",
"electron-builder-util": "0.0.0-semantic-release",
"electron-download-tf": "4.3.1",
"electron-osx-sign": "0.4.5",
"electron-osx-sign": "0.4.6",
"electron-publish": "0.0.0-semantic-release",
"fs-extra-p": "^4.3.0",
"hosted-git-info": "^2.4.2",
Expand All @@ -74,7 +74,8 @@
"update-notifier": "^2.1.0",
"uuid-1345": "^0.99.6",
"yargs": "^8.0.1",
"debug": "2.6.8"
"debug": "2.6.8",
"asar-integrity": "0.0.0-semantic-release"
},
"typings": "./out/electron-builder.d.ts",
"publishConfig": {
Expand Down
6 changes: 5 additions & 1 deletion packages/electron-builder/src/packager/mac.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export function filterCFBundleIdentifier(identifier: string) {
return identifier.replace(/ /g, "-").replace(/[^a-zA-Z0-9.-]/g, "")
}

export async function createApp(packager: PlatformPackager<any>, appOutDir: string) {
export async function createApp(packager: PlatformPackager<any>, appOutDir: string, checksums: { [key: string]: string; }) {
const appInfo = packager.appInfo
const appFilename = appInfo.productFilename

Expand Down Expand Up @@ -135,6 +135,10 @@ export async function createApp(packager: PlatformPackager<any>, appOutDir: stri
use(packager.platformSpecificBuildOptions.category || (<any>buildMetadata).category, it => appPlist.LSApplicationCategoryType = it)
appPlist.NSHumanReadableCopyright = appInfo.copyright

if (checksums != null) {
appPlist.AsarChecksums = JSON.stringify(checksums)
}

const promises: Array<Promise<any | n>> = [
writeFile(appPlistFilename, buildPlist(appPlist)),
writeFile(helperPlistFilename, buildPlist(helperPlist)),
Expand Down
5 changes: 3 additions & 2 deletions packages/electron-builder/src/platformPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Config } from "./metadata"
import { unpackElectron, unpackMuon } from "./packager/dirPackager"
import { BuildInfo, PackagerOptions } from "./packagerApi"
import { readInstalled } from "./readInstalled"
import { computeData } from "asar-integrity"

export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions> {
readonly packagerOptions: PackagerOptions
Expand Down Expand Up @@ -208,7 +209,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
await BluebirdPromise.all(promises)

if (platformName === "darwin" || platformName === "mas") {
await (<any>require("./packager/mac")).createApp(this, appOutDir)
await (<any>require("./packager/mac")).createApp(this, appOutDir, asarOptions == null ? null : await computeData(resourcesPath))
}

await copyFiles(extraResourceMatchers)
Expand Down Expand Up @@ -363,7 +364,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
}

const appInfo = this.appInfo
return pattern.replace(/\$\{([_a-zA-Z./*]+)\}/g, (match, p1): string => {
return pattern.replace(/\${([_a-zA-Z./*]+)}/g, (match, p1): string => {
switch (p1) {
case "productName":
return appInfo.productFilename
Expand Down
25 changes: 4 additions & 21 deletions packages/electron-builder/src/publish/PublishManager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import BluebirdPromise from "bluebird-lst"
import { createHash } from "crypto"
import { Arch, Platform, PlatformSpecificBuildOptions, Target } from "electron-builder-core"
import { CancellationToken } from "electron-builder-http/out/CancellationToken"
import { BintrayOptions, GenericServerOptions, GithubOptions, githubUrl, PublishConfiguration, PublishProvider, S3Options, s3Url, UpdateInfo, VersionInfo } from "electron-builder-http/out/publishOptions"
Expand All @@ -10,7 +9,7 @@ import { HttpPublisher, PublishContext, Publisher, PublishOptions } from "electr
import { BintrayPublisher } from "electron-publish/out/BintrayPublisher"
import { GitHubPublisher } from "electron-publish/out/gitHubPublisher"
import { MultiProgress } from "electron-publish/out/multiProgress"
import { createReadStream, ensureDir, outputJson, writeFile } from "fs-extra-p"
import { ensureDir, outputJson, writeFile } from "fs-extra-p"
import isCi from "is-ci"
import { safeDump } from "js-yaml"
import * as path from "path"
Expand All @@ -21,6 +20,7 @@ import { Packager } from "../packager"
import { ArtifactCreated, BuildInfo } from "../packagerApi"
import { PlatformPackager } from "../platformPackager"
import { WinPackager } from "../winPackager"
import { hashFile } from "asar-integrity"

const publishForPrWarning = "There are serious security concerns with PUBLISH_FOR_PULL_REQUEST=true (see the CircleCI documentation (https://circleci.com/docs/1.0/fork-pr-builds/) for details)" +
"\nIf you have SSH keys, sensitive env vars or AWS credentials stored in your project settings and untrusted forks can make pull requests against your repo, then this option isn't for you."
Expand Down Expand Up @@ -247,8 +247,8 @@ async function writeUpdateInfo(event: ArtifactCreated, _publishConfigs: Array<Pu
}

const version = packager.appInfo.version
let sha2 = new Lazy(() => hash(event.file!, "sha256"))
let sha512 = new Lazy(() => hash(event.file!, "sha512"))
let sha2 = new Lazy(() => hashFile(event.file!, "sha256"))
let sha512 = new Lazy(() => hashFile(event.file!, "sha512"))
const isMac = packager.platform === Platform.MAC

for (const publishConfig of publishConfigs) {
Expand Down Expand Up @@ -421,23 +421,6 @@ export async function getPublishConfigs(packager: PlatformPackager<any>, targetS
return await (<Promise<Array<PublishConfiguration>>>BluebirdPromise.map(asArray(publishers), it => getResolvedPublishConfig(packager, typeof it === "string" ? {provider: it} : it, arch)))
}

function hash(file: string, algorithm: string) {
return new BluebirdPromise<string>((resolve, reject) => {
const hash = createHash(algorithm)
hash
.on("error", reject)
.setEncoding("hex")

createReadStream(file)
.on("error", reject)
.on("end", () => {
hash.end()
resolve(<string>hash.read())
})
.pipe(hash, {end: false})
})
}

function isSuitableWindowsTarget(target: Target) {
return target.name === "nsis" || target.name.startsWith("nsis-")
}
Expand Down
2 changes: 1 addition & 1 deletion packages/electron-publisher-s3/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
],
"dependencies": {
"fs-extra-p": "^4.3.0",
"aws-sdk": "^2.60.0",
"aws-sdk": "^2.61.0",
"mime": "^1.3.6",
"electron-publish": "~0.0.0-semantic-release",
"electron-builder-util": "~0.0.0-semantic-release"
Expand Down
1 change: 1 addition & 0 deletions test/out/mac/__snapshots__/macPackagerTest.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Object {
exports[`one-package 2`] = `
Object {
"AsarChecksums": "{\\"app.asar\\":\\"hash\\",\\"electron.asar\\":\\"hash\\"}",
"BuildMachineOSBuild": "16E195",
"CFBundleDisplayName": "Test App ßW",
"CFBundleDocumentTypes": Array [
Expand Down
10 changes: 10 additions & 0 deletions test/src/helpers/packTester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,16 @@ async function checkMacResult(packager: Packager, packagerOptions: PackagerOptio
// checked manually, remove to avoid mismatch on CI server (where TRAVIS_BUILD_NUMBER is defined and different on each test run)
delete info.CFBundleVersion
delete info.NSHumanReadableCopyright

const checksumData = info.AsarChecksums
if (checksumData != null) {
const checksums = JSON.parse(checksumData)
for (const name of Object.keys(checksums)) {
checksums[name] = "hash"
}
info.AsarChecksums = JSON.stringify(checksums)
}

if (checkOptions.checkMacApp != null) {
await checkOptions.checkMacApp(packedAppDir, info)
}
Expand Down

0 comments on commit 3e28ae2

Please sign in to comment.