Giter Site home page Giter Site logo

winsign's Introduction

winsign

Documentation Status

winsign is a python module for signing and manipulating Authenticode signatures in PE and MSI files.

  • Works on Python 3.7 and up.
  • Free software: MPL2

Requirements

Most dependencies are specified in requirements/base.txt, however, currently you also need osslsigncode installed to perform signing. This utility can be fetched from your distribution's package repository, or from e.g. https://github.com/theuni/osslsigncode

Signing MSIX/APPX files currently requires Mozilla's fork of msix-packaging.

Installation

pip install winsign

CLI Usage

usage: winsign [-h] --certs CERTS --key PRIV_KEY [-n COMMENT] [-i URL] -d
               {sha1,sha256} [-t {old,rfc3161}] [-v] [-q]
               infile [outfile]

positional arguments:
  infile            unsigned file to sign
  outfile           where to write output to. defaults to infile

optional arguments:
  -h, --help        show this help message and exit
  --certs CERTS     certificates to include in the signature
  --key PRIV_KEY    private key used to sign
  -n COMMENT        comment to include in signature
  -i URL            url to include in signature
  -d {sha1,sha256}  digest to use for signing. must be one of sha1 or sha256
  -t {old,rfc3161}
  -v, --verbose
  -q, --quiet

Future plans

  • Stop using osslsigncode for PE signatures
  • Refactor code so that osslsigncode functionality is in its own module
  • Add python support for MSI, then we can drop dependency on osslsigncode

Development

Highly recommended to create a virtualenv, then run:
  • python setup.py develop
  • make your changes to the source files
  • run local tests: tox
upon successful r+ and merging to master branch, you need to release a new version on PyPi.
  • edit setup.py to adjust the version
  • generate .whl file locally: python setup.py bdist_wheel
  • file will exist in: ./dist/winsign-{version}-py3-none-any.whl
  • (assuming you have pypi access to upload)
  • upload to pypi: twine upload --verbose dist/winsign-{version}-py3-none-any.whl

Credits

winsign's People

Contributors

agashlin avatar bhearsum avatar catlee avatar gbrownmozilla avatar jcristau avatar jmaher avatar masterwayz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

winsign's Issues

signed files unnecessarily embed the "dummy" cert

winsign starts by signing with a dummy key, then replace the signature with the real one, but apparently keep/copy the cert from the dummy signature to the final binary, which seems a bit ugly.

Support for signing PowerShell scripts

It would be awesome if this project added support for signing PowerShell scripts given the private key and a string that contains the PS. As far as I know, no other cross-platform project supports this right now.

It looks like, to do this, we need to encode the signature (which I don't understand how the sig is generated) in the following way:

def format_binary_sig(contents):
    chunks = lambda x, size = 64 : [x[i:i+size] for i in range(0, len(x), size)]

    contents = base64.b64encode(contents)
    contents = '\n# '.join(chunks(contents.decode('utf-8'), size = 64))

    contents = '\n# SIG # Begin signature block\n# %s\n# SIG # End signature block\n' % contents
    return contents.replace('\n', '\r\n')

License?

Hey! What is this project licensed under?

(note: MIT license preferred for my use case!)

Support osslsigncode 2.x

osslsigncode 2.x changed in a way that broke winsign (at least, in the way we use it in https://github.com/mozilla-releng/scriptworker-scripts/tree/master/signingscript). The error we ended up with was:

2021-09-02 17:54:03,658 - winsign.sign - DEBUG - Attaching new signature
2021-09-02 17:54:03,659 - winsign.osslsigncode - DEBUG - running: ['osslsigncode', 'attach-signature', '-sigin', '/tmp/tmpse3aiptn', '-in', PosixPath('/app/workdir/public/build/setup.exe'), '-out', PosixPath('/app/workdir/public/build/setup.exe-new')]
2021-09-02 17:54:03,675 - winsign.osslsigncode - ERROR - osslsigncode failed when running attach-signature:
2021-09-02 17:54:03,676 - winsign.osslsigncode - ERROR - Use the "-CAfile" option to add one or more trusted CA certificates to verify the signature.
2021-09-02 17:54:03,676 - winsign.osslsigncode - ERROR - Failed
2021-09-02 17:54:03,676 - winsign.osslsigncode - ERROR - 
2021-09-02 17:54:03,676 - winsign.sign - ERROR - Couldn't write new signature
2021-09-02 17:54:03,676 - winsign.sign - DEBUG - Exception:
Traceback (most recent call last):
  File "/app/lib/python3.8/site-packages/winsign/sign.py", line 139, in sign_file
    write_signature(infile, outfile, newsig)
  File "/app/lib/python3.8/site-packages/winsign/osslsigncode.py", line 274, in write_signature
    osslsigncode(cmd)
  File "/app/lib/python3.8/site-packages/winsign/osslsigncode.py", line 92, in osslsigncode
    raise OSError("osslsigncode failed")
OSError: osslsigncode failed

...which seems to indicate we need to provide a certificate (the root certificate?) when attaching signatures. It's possible there's other things that will need fixing as well.

RFC3161 timestamp without certReq set doesn't validate

When generating a RFC3161 timestamp request (-t rfc3161), winsign sets the certReq field to False. This seems to produce a cross signature that Windows fails to accept, signtool says:

SignTool Error: WinVerifyTrust returned error: 0x80092004
        Cannot find object or property.

Changing this field to True allows this to succeed.

I have some signatures from 2021-05-17 that I generated with -t rfc3161, these contain the full cert chain and verify correctly. Unlikely as it seems, I think that DigiCert (the default TSA) started respecting certReq in just the last few days. Their RFC3161 support page was just updated 2021-05-06, with certificate and chain files that have that as the last modified date, so they may have recently been working on dropping the chain from the response. Every other RFC3161 timestamp server I tried has the same behavior, and the spec requires it.

Add open source software license

This Mozilla repository has been identified as lacking a license. Consistent with Mozilla's Licensing Policy an open source license should be applied to the code in this repository.

Please add an appropriate LICENSE.md file to the root directory of the project. In general, Mozilla's licensing policies are as follows:

  • Client-side products created by Mozilla employees or contributors should use the Mozilla Public License, Version 2.0 (MPL).

  • Server-side products or utilities that support Mozilla products may use either the MPL or the Apache License 2.0 (Apache 2.0).

In special cases, another license might be appropriate. If the repository is a fork of another repository it must apply the license of the original. Similarly, another license might be appropriate to match that of a broader project (for example Rust crates that Firefox depends on are published under an Apache 2.0 / MIT dual license, as that is the dual license used by the Rust programming language and projects).

Please ensure that any license added to the LICENSE.md file matches other licensing information in the repository (for example, it should match any license indicated in a setup.py or package.json file).

Mozilla staff can access more information in our Software Licensing Runbook – search for “Licensing Runbook” in Confluence to find it.

If you have any questions you can contact Daniel Nazer who can be reached at dnazer on Mozilla email or Slack.

OPENLIC-2023-01

Handle CRLF line endings in cert files

We have some logic that assumes \n delimited newlines. This fails with errors like this if they instead contain Windows line endings. It would be nice to either normalize newlines to \n in this function, or at least raise a less cryptic error.

I'm a bit confused though, becasue the Python docs for open state:

When reading input from the stream, if newline is None, universal newlines mode is enabled. Lines in the input can end in '\n', '\r', or '\r\n', and these are translated into '\n' before being returned to the caller

The open call in signingscript does not specify newline, so afaict it should be translating newlines to \n automatically. Maybe that doesn't work for binary streams? (If that's the case, the docs make no mention of this).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.