@talex/electron-windows-store
Version:
Compile Electron Apps into Windows Store AppX packages
242 lines (213 loc) • 22.5 kB
JavaScript
const fs = require('fs-extra')
const path = require('path')
const mockery = require('mockery')
const ChildProcessMock = require('../fixtures/child_process')
const sign = require('../../lib/sign')
const utils = require('../../lib/utils')
describe('Sign', () => {
const tmpDir = path.join(require('os').tmpdir(), 'electron-windows-store-cert-test')
let passedArgs = []
let passedProcess = []
const cpMock = {
spawn(_process, _args) {
passedProcess.push(_process)
passedArgs.push(_args)
return new ChildProcessMock()
}
}
before(() => {
fs.ensureDirSync(tmpDir)
})
after(() => {
fs.removeSync(tmpDir)
})
afterEach(() => {
mockery.deregisterAll()
passedArgs = []
passedProcess = []
})
describe('signappx()', () => {
it('should attempt to sign the current app', function (done) {
const programMock = {
inputDirectory: '/fakepath/to/input',
outputDirectory: '/fakepath/to/output',
windowsKit: '/fakepath/to/windows/kit/bin',
packageName: 'testapp',
devCert: 'fakepath/to/devcert.pfx'
}
mockery.registerMock('child_process', cpMock)
sign.signAppx(programMock)
.then(() => {
const expectedScript = path.join(programMock.windowsKit, 'signtool.exe')
const expectedPfxFile = programMock.devCert
const expectedAppx = path.join(programMock.outputDirectory, `${programMock.packageName}.appx`)
const expectedParams = ['sign', '-f', expectedPfxFile, '-fd', 'SHA256', '-v', expectedAppx]
passedProcess.length.should.equal(1)
passedProcess[0].should.equal(expectedScript)
passedArgs[0].should.deep.equal(expectedParams)
done()
})
})
it('should pass along the certificate password', function () {
const programMock = {
inputDirectory: '/fakepath/to/input',
outputDirectory: '/fakepath/to/output',
windowsKit: '/fakepath/to/windows/kit/bin',
packageName: 'testapp',
devCert: 'fakepath/to/devcert.p12',
certPass: '12345'
}
mockery.registerMock('child_process', cpMock)
return sign.signAppx(programMock)
.then(() => {
const expectedScript = path.join(programMock.windowsKit, 'signtool.exe')
const expectedPfxFile = programMock.devCert
const expectedAppx = path.join(programMock.outputDirectory, `${programMock.packageName}.appx`)
const expectedParams = ['sign', '-f', expectedPfxFile, '-fd', 'SHA256', '-v', '-p', '12345', expectedAppx]
passedProcess.length.should.equal(1)
passedProcess[0].should.equal(expectedScript)
passedArgs[0].should.deep.equal(expectedParams)
})
})
it('should reject if no certificate is present', function () {
const programMock = {}
return sign.signAppx(programMock).should.be.rejected
})
})
describe('makeCert()', () => {
it('should not attempt to import certificate when install === false', function (done) {
mockery.registerMock('child_process', cpMock)
sign.makeCert({
publisherName: 'CN=Test',
certFilePath: tmpDir,
install: false,
program: {
windowsKit: '/fake/kit'
}
})
.then(() => {
passedArgs.every((args) => {
return args.every(arg => arg.indexOf('Import-PfxCertificate') === -1)
}).should.equal(true)
done()
})
.catch(() => {})
})
})
describe('isValidPublisherName()', () => {
const windowsSdkPath = process.arch === 'x64' ?
'C:\\Program Files (x86)\\Windows Kits\\10\\bin\\x64' :
'C:\\Program Files\\Windows Kits\\10\\bin\\x64';
const makecertExe = path.join(windowsSdkPath, 'makecert.exe')
const pvkFileName = path.resolve(__dirname, 'bogus-private-key.pvk');
const skipMakeCertExecution = !fs.existsSync(makecertExe) || !fs.existsSync(pvkFileName)
const scenarios = [{
publisherName: ''
}, {
publisherName: 'CN='
}, {
publisherName: 'CN=-'
}, {
publisherName: 'cn=lower, ou=case'
}, {
publisherName: 'CN=first.last'
}, {
publisherName: 'CN="Pointlessly quoted"'
}, {
publisherName: 'CN=no,o=spaces'
}, {
publisherName: 'CN=" Leading and Trailing Spaces "'
}, {
publisherName: 'CN=Common Name,O=Some organization'
}, {
publisherName: 'O="Quoted comma, Inc."'
}, {
publisherName: 'CN=!@#$^&*()[]{}<>|\/.~\'-=,O="Symbols are Cool, LLC"'
}, {
publisherName: 'OU=Sales+CN=J. Smith,O=Multi-valued'
}, {
publisherName: 'CN=Duplicate+CN=Attribute'
}, {
publisherName: 'OU=Trailing plus+',
}, {
publisherName: 'CN=trailing comma,',
}, {
publisherName: 'CN="Escaped\\ and\\ quoted\\ spaces"'
}, {
publisherName: 'CN=First M Last, O="Acme, Inc."'
}, {
publisherName: 'CN=Marshall T. Rose, O=Dover Beach Consulting, L=Santa Clara,ST=California, C=US'
}, {
publisherName: 'CN=FTAM Service, CN=Bells, OU=Computer Science,\nO=University College London, C=GB'
}, {
publisherName: 'CN=Markus Kuhn, O=University of Erlangen, T=Mr., C=DE'
}, {
publisherName: 'CN=Steve Kille,\n O=ISODE Consortium,\n C=GB'
}, {
publisherName: 'CN=Christian Huitema; O=INRIA; C=FR'
}, {
publisherName: 'CN=This is a really long distinguished name: 2048 chars!........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................'
}, {
publisherName: 'CN=Even longer: 4096 chars 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678'
}, {
publisherName: 'CN=Long enough for anyone: 8192 chars 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123'
}, {
publisherName: 'CN=L. Eagle, O="Sue, Grabbit and Runn", C=GB'
}, {
publisherName: 'O=No CN'
}, {
publisherName: 'SERIALNUMBER=1'
}, {
publisherName: 'DC=A,CN=B,OU=C,O=D,STREET=123 Main St.,L=Big City,ST=Nowhere,C=XX,SN=Surname,GN=Given name,E=nobody@example.com,S=E,T=F,G=G,I=1.2.3.4'
}, {
publisherName: 'CN="+"',
}, {
publisherName: 'CN=X+'
}, {
publisherName: 'X',
expectInvalid: true
}, {
publisherName: 'CN=X,UID=userId',
expectInvalid: true
}, {
publisherName: 'CN=\ Escaped leading space"',
expectInvalid: true
}, {
publisherName: 'CN="Quotation \\" Mark"',
expectInvalid: true
}, {
publisherName: 'CN=X,DNQ=qualifier',
expectInvalid: true
}, {
// According to RFC1779 and RFC2243 this should be legal but MakeCert.exe does not seem to accept it
publisherName: 'CN=Sue\\, Grabbit and Runn',
expectInvalid: true
}]
scenarios.forEach((scenario) => {
const actualResult = sign.isValidPublisherName(scenario.publisherName)
let nameToPrint = scenario.publisherName.replace(/\n/g, '\\n')
if (nameToPrint.length > 60)
nameToPrint = nameToPrint.slice(0,61) + '...'
// Compare pre-determined checks (previously confirmed with makecert.exe)
it(`return ${scenario.expectInvalid ? 'false' : 'true'} for ${nameToPrint}`, () => {
actualResult.should.equal(!scenario.expectInvalid, scenario.publisherName)
})
// Run makecert.exe and check whether or not it fails with this publisherName
if (!skipMakeCertExecution) {
const rnd = Date.now() + '-' + Math.floor(Math.random()*10000)
const crtFileName = path.join(tmpDir, `makecert-${rnd}.crt`)
const makecertArgs = ['-r', '-h', '0', '-n', scenario.publisherName, '-eku', '1.3.6.1.5.5.7.3.3', '-pe', '-sv', pvkFileName, crtFileName]
it(`makecert.exe should ${scenario.expectInvalid ? 'fail' : 'succeed'} for ${nameToPrint}`, () => {
return utils.executeChildProcess(makecertExe, makecertArgs)
.then(() => { return true })
.catch(() => { return false })
.should.eventually.equal(!scenario.expectInvalid)
})
}
})
if (skipMakeCertExecution) {
it.skip('should be re-tested against actual MakeCert.exe from SDK')
}
})
})