AMO/SigningService/API
Contents
General Info
Abstract
This document describes how addons are signed to be automatically in Mozilla's Marketplace infrastructure.
Definitions
- endpoint-url
- The full URI for the service including the version string for the API as defined below.
- version string
- This revision of the protocol is 1.0 so the version string is "/1.0/".
- root certificate
- The signing CA's root certificate in standard X.509 format. This certificate will be included in each build of the user agent.
- generated key and certificate
- An very short lived private and public key pair that are generated in an automated fashion, on demand. The public key is then certified by the CA root certificate.
- unsigned archive
- A JAR file that has been uploaded by a developer but not signed by the service yet.
- signed archive
- A JAR file that has been created by Zamboni to include the contents of the unsigned archive and the generated manifest and signature files.
- manifest file
- A file describing the contents of a JAR file. Format detailed here.
- signature file
- A file of the same format as the manifest file that contains a single entry for the manifest file. Official format detailed here. Note that XPI signing is an incompatible subset of JAR signing due to changes made in how XPIs are verified for improved security.
- app id
- A unique identifier for the combination of addon name and version that will be used in the generated key and certificate. A strong preference for human readable.
Related documentation
- JAR signing
- JDK documentation
- JAR validation
- JDK documentation
- PKCS#7
- Cryptographic Message Syntax is a brief intro with links
Data formats
The data formats are described in depth in the JDK documentation. There are three basic formats being dealt with:
- Zip archives
- An HTTP header like format for archive manifests and signatures
- PKCS#7 detached signature in DER format
Components
- Signing clients
- https://github.com/mozilla/signing-clients/
signing-clients is just a simple library for generating, parsing, and formatting the manifest and signature file formats.
The actual signing service. This is the same code base as the receipt signing service but runs in a separate process space to provide a degree of separation between app signing, receipt signing, and addon signing credentials.
- Zamboni, packaged app handling specifically
- https://github.com/mozilla/zamboni/blob/master/lib/crypto/packaged.py
Zamboni is responsible for receiving and storing an uploaded application archive, generating manifest and signature files for it via the signing-clients library, requesting a signature from the trunion signing service, and creating a new signed application archive containing the additional three files.
API
- POST http
- //<endpoint-url>/sign_addon OR http://<endpoint-url>/sign/addon :
- This takes two arguments:
- the archive's signature file as multipart/form-data as an input with the name "file" with a filename included.
- the app id for this XPI at this version.
- It then returns a PKCS#7 detached signature of the uploaded content in a JSON object with a single key and value pair. The key is the uploaded content's specified filename with its extension(".sf") replaced with ".rsa". The value is a base64 encoded representation of the PKCS#7 data.
Example request
POST /1.0/sign_addon HTTP/1.1 Host: localhost:5000 Content-Length: 306 Content-Type: multipart/form-data; boundary=df8e3fdaf425408e956aff8ca19d0263 Accept-Encoding: gzip, deflate, compress Accept: */* User-Agent: python-requests/0.14.2 CPython/2.7.1 Darwin/11.4.2 --df8e3fdaf425408e956aff8ca19d0263 Content-Disposition: form-data; name="id" Content-Type: text/plain
digital-doughnuts-addon-v1.0 --df8e3fdaf425408e956aff8ca19d0263 Content-Disposition: form-data; name="file"; filename="zigbert.sf" Content-Type: application/octet-stream Signature-Version: 1.0 MD5-Digest-Manifest: PTUbaADVign9DDK3ntq9ww== SHA1-Digest-Manifest: FkVPRYqW9UT8kcbm8VS08TIWsH4= --df8e3fdaf425408e956aff8ca19d0263--
Example response
Response body truncated for brevity.
HTTP/1.0 200 OK Server: PasteWSGIServer/0.5 Python/2.6.8 Date: Wed, 01 Oct 2014 20:43:05 GMT Content-Type: application/json; charset=UTF-8 Content-Length: 3607 {"zigbert.rsa": "MIIKfQYJKoZIhvcNAQcCoIIKbjCCCmoCAQExCzAJBgUrDgMCGgUAMAsGCSq...=="}
HTTP response codes
- 200 OK
- The request was processed successfully and the server is returning a PKCS#7 signature
- 400 Bad request
- The request body was incorrectly formatted
- 401 Unauthorized
- The authentication credentials are invalid. At the moment authorization consists of a simple whitelist of IPs. In the future this may be used to indicate a BrowserID or other authentication mechanism has failed or the credentials are not authorized to use the service.
- 409 Conflict
- A certificate has already been generated for the app id provided
- 503 Service Unavailable
- Indicates that the server(s) are undergoing maintenance.