Extension Manager:Addon Update Security:Signature
This page sets out more details about the digital signature method of securing add-on update manifests.
Update Public Key
In order to verify the signature in the update manifest, a public key is required. This must be included in the original add-on xpi. Including the key in the install.rdf makes checking for a key on install and retrieving the key at update time easier than the alternative option of including it as a file in the xpi.
The key shall be DER encoded and then base64 encoded for inclusion as an em:updateKey resource in the install manifest. An example of this is below:
<?xml version="1.0"?> <RDF:RDF xmlns:em="http://www.mozilla.org/2004/em-rdf#" xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <RDF:Description about="urn:mozilla:install-manifest"> <em:id>TabSidebar@blueprintit.co.uk</em:id> <em:version>2.0a1</em:version> <em:name>Tab Sidebar</em:name> <em:description>Displays previews of your tabs in your sidebar.</em:description> <em:updateURL>http://www.oxymoronical.com/web/firefox/TabSidebar/update.rdf</em:updateURL> <em:targetApplication> <RDF:Description> <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <em:minVersion>1.5</em:minVersion> <em:maxVersion>3.0a5pre</em:maxVersion> </RDF:Description> </em:targetApplication> <em:publicKey>MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8tygA/cOMS/cyFn3Lf30Dskkd Q0i6NlLfKVxTYUmLge/tEb3QMHlBdM9D0mMpzybq7rFI7aFscUFEcDo9WVd5ieyZ cPotUd1WyUXZHXKluMfkE4asnXedLcICqrXEUJDxeWHSA36FrMW4uASxbl42/Ibi e/liyRgPpmzDged+jQIDAQAB</em:publicKey> </RDF:Description> </RDF:RDF>
Update Manifest Signature
The update signature is generated from a string of text that is pulled out of the update manifest. It is important that this string remains the same for a given update manifest no matter how the manifest was serialized. This is partly because our rdf code generally changes the format of the serialized data.
To ensure this the following form is used for the text string:
<updatestring> ::= <id> <versionlist> <versionlist> ::= <version> | <version> <versionlist> <version> ::= ":" <versionnumber> <targetapplist> <targetapplist> ::= <targetapp> | <targetapp> <targetapplist> <targetapp> ::= "(" <id> ":" <minVersion> ":" <maxVersion> ":" <updateLink> <opt-updateHash> ")" <opt-updateHash> ::= "" | ":" <updateHash>
Note that the strings in the targetapplist are sorted in alphabetical order before being concatenated. This is because the update manifest format does not include any ordering information about the target application arcs (correctly) so we must introduce some mechanism that leaves the order the same each time.
The string includes the add-on's id, the version of every listed update and all the target application information as well as the url of the updated xpi and if present the hash for that xpi.
This is then signed using the author's private key. The signature is base64 encoded and added as an em:signature resource to the add-on's update manifest. Following is an example update manifest with an included signature:
<?xml version="1.0"?> <RDF:RDF xmlns:em="http://www.mozilla.org/2004/em-rdf#" xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <RDF:Description RDF:about="urn:mozilla:extension:TabSidebar@blueprintit.co.uk"> <em:updates> <RDF:Seq> <RDF:li RDF:resource="urn:mozilla:extension:TabSidebar@blueprintit.co.uk:1.1.5"/> </RDF:Seq> </em:updates> <em:signature>J9bFaHr+u1PiJ777xlV2ApUTNkgbVXh/NfjdBXDlkZ8CjSsHXhFmuYD6AJqr/nYk 1qkLryqEEdYo3NrLotpc5Kgy2r1J0wghNUDCNnjwjzh9LJT38KCnoqv2djb5VOmN 1HYLHwn3+qD+DdGBUy8VV3EeRzxiGL+wjXn0o4T5Ok4=</em:signature> </RDF:Description> <RDF:Description RDF:about="urn:mozilla:extension:TabSidebar@blueprintit.co.uk:1.1.5"> <em:version>1.1.5</em:version> <em:targetApplication> <RDF:Description> <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <em:minVersion>2.0b1</em:minVersion> <em:maxVersion>2.0.0.*</em:maxVersion> <em:updateLink>http://www.oxymoronical.com/site/files/845/default/3/TabSidebar-1.1.5.xpi</em:updateLink> </RDF:Description> </em:targetApplication> </RDF:Description> </RDF:RDF>
Note that the location of the signature requires multiple signatures in the manifest if the manifest contains information about multiple add-ons. This allows different add-ons to be signed by different keys.
Algorithms and Key Types
In order to make this work we must choose an appropriate key type and hashing algorithm for generating the digital signature. As far as the implementation goes this choice is largely irrelevant. So long as NSS supports the choice it is a trivial change to make the code work.
Key Type
- RSA
- DSA
Must also consider key size.
Hashing Algorithm
If the key type is DSA then the hashing algorithm must be SHA1, otherwise any of the following may be used:
- MD2
- MD5
- SHA1
- SHA256
- SHA384
- SHA512
If we select SHA1 as the hashing algorithm then either key type can be chosen, indeed it would not be necessary to standardise on the key type at all.