Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Mono's signcode for non-Windows builds #505

Closed
wants to merge 3 commits into from
Closed

Add Mono's signcode for non-Windows builds #505

wants to merge 3 commits into from

Conversation

kevinmartin
Copy link
Contributor

Since signtool.exe is broken with Mono, use Mono's built-in signcode tool.

This update signcode is available on the $PATH and that the developers signing the the release needs to put different options in --signWithParams to accommodate for the change.

Sample signing:

Update-Mono.exe --releasify ./app.1.0.0.nupkg --signWithParams -spc authenticode.spc -v authenticode.pvk -a sha1 -$ commercial -n My\ Application -i http://www.example.com/ -t http://timestamp.verisign.com/scripts/timstamp.dll -tr 10

More details can also be found at MDN: https://developer.mozilla.org/en-US/docs/Signing_an_executable_with_Authenticode

Fixes: #496

@kevinmartin
Copy link
Contributor Author

@paulcbetts I'm not much of a C# guy, but does this look good?

@anaisbetts
Copy link
Contributor

@kevinmartin I'm not super excited to hoist the "You need different params" onto users, are we 100% sure that we can't get signtool.exe to work?

@kevinmartin
Copy link
Contributor Author

Like I said above, @paulcbetts, I'm not a C# guy.

I tried to look for a solution though and nothing. They all recommend either using signcode or osslsigncode.

@anaisbetts
Copy link
Contributor

@kevinmartin No worries, thanks for the PR - I'll look into it and bite the bullet if there's no other option

@kevinmartin
Copy link
Contributor Author

@paulcbetts, Excellent. I don't mean to be pushy, but when do you expect to be able to merge and release this?

#if MONO
// Use Mono's signcode tool
var exe = "signcode";
#endif;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Xamarin Studio choked on that for me, you don't need to use ; after a directive.

Also, #else exists, it's better than two if VAL / if !VAL blocks 👍

@fasterthanlime
Copy link
Contributor

The only problem with that branch is that signcode will try to read the pvk's password from standard input. Not sure yet how to deal with that.

@fasterthanlime
Copy link
Contributor

signcode will try to read the pvk's password from standard input

The workaround to that is to import the private key with mono's certmgr

certmgr -importKey -c -v -p "PFX_PASSWORD" My PFX_PATH

Explanation:

  • -c adds/dels/puts certificate
  • -v is verbose (helpful because fragile)
  • -p YOUR_PASSWORD is self-explanatory. If it's the wrong password, it'll complain with Invalid MAC - file may have been tampered!
  • My is for Personal store, see list of values in X509Stores.cs
  • PFX_PATH is the path to your pfx file

Once that's done, you can (should!) delete the pfx, and omit the -v authenticode.pvk part from the signcode params.

(Sorry if it I'm hijacking this PR, hopefully it'll help people who google this info)

@fasterthanlime
Copy link
Contributor

Annoyingly, Mono's signcode creates a .bak file for every exe it signs, and there's no way to disable it without recompiling, so the setup ends up much larger than needed (52MB to 80MB for me).

Hence, I'd rather use osslsigncode, personally. Reopening #521 since it would support both usecases, will submit PR later today.

@anaisbetts
Copy link
Contributor

@fasterthanlime Can't we just delete the backup file after-the-fact?

@fasterthanlime
Copy link
Contributor

@paulcbetts yes, if you add a codepath for it in Update, but even then it produces/produced invalid signatures (for me). My understanding from a cursory look at signcode's source code is that it's experimental and not to be used in production.

cf. #522 for longer rants

@fasterthanlime
Copy link
Contributor

if you add a codepath for it in Update

in case it's non-obvious: in the installer building process, signPEFile is called a bunch of times — for the main .exe, but also for the Update.exe included in the embedded zip.

If Update doesn't delete all the .bak, some of them are going to end up in the .nupkg, which itself ends up in the Setup.exe, which is no good 🐼

@anaisbetts
Copy link
Contributor

This is a ton of good research, huge thanks to both of you. So my plan is:

  1. Still try to get signtool.exe working in Wine, I think we can make it happen if we ship our own msvcrt.dll
  2. If not, we'll probably get one of either the osslsigntool or the mono signtool app working, and try to make it a bit easier for folx (auto-convert their certificate, etc etc).

@fasterthanlime
Copy link
Contributor

Sounds like a plan. I'm in no great hurry for this to land as I managed to get the whole chain running in our forks of Squirrel.WIndows + grunt-electron-installer.

@paulcbetts would you consider - at some point - supporting osslsigntool even if you get signtool.exe working ? it would still be a good alternative (only deps are openssl and curl, works damn fast).

@dustinblackman
Copy link

dustinblackman commented Dec 9, 2016

Over a year later, I'm assuming this PR is no longer valid? This issue still exists with the latest Wine, Mono, and OSX. Related: electron/windows-installer#27

@fasterthanlime
Copy link
Contributor

@dustinblackman personally, I gave up and am now using native Windows workers to package and sign installers.

@dustinblackman
Copy link

dustinblackman commented Dec 11, 2016

@fasterthanlime Built a dirty workaround instead as I don't feel like booting up VMs just for signing. For all you Googlers ending up here looking for a solution, this may do it. https://github.com/dustinblackman/mono-signtool

@fasterthanlime
Copy link
Contributor

@dustinblackman marketing tip: don't call it a dirty hack, call it a "drop-in replacement" 🙂

@andreineculau
Copy link

for those that are running into issues with the "drop-in replacement" 😉 mentioned in #505 (comment) (for me it just hangs because it probably fails in calling osslsigncode and it doesn't handle that properly due to the for-loop-sleep pattern), I'm actually having success with the following process:

  • install osslsigncode, e.g. on ubuntu with sudo apt-get install osslsigncode or on osx/linuxbrew with brew install osslsigncode

  • for each *.{exe,dll,node} file, call osslsigncode:

mv "$f" "$f.unsigned"
osslsigncode -h sha1 -in "$f.unsigned" -out "$f.sha1-signed" -t http://timestamp.verisign.com/scripts/timstamp.dll -pkcs12 mycert -pass mypass
osslsigncode -h sha256 -in "$f.sha1-signed" -out "$f" -t http://timestamp.verisign.com/scripts/timstamp.dll -pkcs12 mycert -pass mypass
rm "$f.unsigned"
rm "$f.sha1-signed"
  • releasify without any signWithParams i.e. no code-signing
  • call osslsigncode once more, for the installer exe

@collinbachi
Copy link

@andreineculau I ran into the same issue with "mono-signtool" freezing up during the call to osslsigncode.

When I attempt your workaround, Squirrel introduces an unsigned exe at some point when creating the installer. Post-installation, the install directory contains:
MyProgram.exe (unsigned)
app-1.0.0/MyProgram.exe (signed)
app-1.0.0/*.dll (signed)

I'm not sure at what point the unsigned exe is being created, or whether this is configurable somewhere.

For now, the only way I can create a working installer is to build on Windows and let Squirrel do the signing.

@kevinmartin kevinmartin deleted the patch-2 branch September 17, 2019 14:54
@sachinrekhi
Copy link

sachinrekhi commented Nov 5, 2019

@andreineculau @collinbachi I'm running into the same issue @collinbachi mentioned when I attempt to manually sign the contents using signcode npm module, run electron-winstaller and then also sign the installer.

When I ultimately install the application using the installer, I notice that the root directory application exe is not signed nor is squirrel.exe, despite both being signed prior to creating the installer.

Did anyone find a workaround? Even though I can now manually sign the contents and the installer, after installation somehow several EXEs are left unsigned. Seems like something that happens during the electron-winstaller process.

@andreineculau
Copy link

EDIT: I see that I missed providing --nest to the 2nd call to osslsigncode. Can this be the reason?


I don't know what to say, but below you have the exact Makefile excerpt that we run regularly on travis ci (ubuntu xenial) to build signed win32 binaries

	cd "$(DIST_TARGET_DIR)" && \
		$(FIND_Q_NOSYM) . -type f \( -name "*.exe" -o -name "*.dll" -o -name "*.node" \) -print | while read f; do \
		$(ECHO_DO) "Signing $$f..."; \
		$(MV) "$$f" "$$f.unsigned"; \
		$(OSSLSIGNCODE) \
			-h sha1 \
			-in "$$f.unsigned" \
			-out "$$f.sha1-signed" \
			-t http://timestamp.verisign.com/scripts/timstamp.dll \
			-pkcs12 $(GIT_ROOT)/$(WIN32_P12) \
			-pass $(WIN32_P12_PASS); \
		$(OSSLSIGNCODE) \
			-nest \
			-h sha256 \
			-in "$$f.sha1-signed" \
			-out "$$f" \
			-t http://timestamp.verisign.com/scripts/timstamp.dll \
			-pkcs12 $(GIT_ROOT)/$(WIN32_P12) \
			-pass $(WIN32_P12_PASS); \
		$(RM) "$$f.unsigned"; \
		$(RM) "$$f.sha1-signed"; \
		$(ECHO_DONE); \
	done
	$(ELECTRON_INSTALLER_WINDOWS) \
		--src "$(DIST_TARGET_DIR)" \
		--dest dist/installers/ \
		--platform $(DIST_TARGET_OS) \
		--arch $(DIST_TARGET_ARCH)
	cd dist/installers && \
		$(ECHO) "$(PKG_NAME_EIW)-$(PKG_VSN)-setup.exe" | while read f; do \
		$(ECHO_DO) "Signing $$f..."; \
		$(MV) "$$f" "$$f.unsigned"; \
		$(OSSLSIGNCODE) \
			-h sha1 \
			-in "$$f.unsigned" \
			-out "$$f.sha1-signed" \
			-t http://timestamp.verisign.com/scripts/timstamp.dll \
			-pkcs12 $(GIT_ROOT)/$(WIN32_P12) \
			-pass $(WIN32_P12_PASS); \
		$(OSSLSIGNCODE) \
			-nest \
			-h sha256 \
			-in "$$f.sha1-signed" \
			-out "$$f" \
			-t http://timestamp.verisign.com/scripts/timstamp.dll \
			-pkcs12 $(GIT_ROOT)/$(WIN32_P12) \
			-pass $(WIN32_P12_PASS); \
		$(RM) "$$f.unsigned"; \
		$(RM) "$$f.sha1-signed"; \
		$(ECHO_DONE); \
	done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants