Why would you want to sign a widget?
For the same reasons why you would sign a document or an email if you're GNUPG savvy. To say it comes from you and as an added bonus to show that the files (contents) have their integrity intact (i.e. they have not been tampered with!).
If you want your widget to be distributed by a major operator, you need to have them sign your widget in order to approve of it. If later the operator has found your Widget to be malicious, widget signatures can be revoked using OCSP verification.
How does it work
- You have a Widget package with a list of files
- Each file gets hashed, e.g.
- Those filenames and hashes are put in a manifest and again all hashed, then signed with a private key
For some godforsaken reason we are using XML
Signatures, however I suggest you read
Java's jarsigner man
we're doing everything that
jarsigner is doing, but using very complex and
fragile W3C XML suite of technologies. Whoops.
Signing a widget with xmlsec1
If you prefer a user interface to signing a widget you should instead look at the LiMo supported BONDI SDK and http://bondisdk.limofoundation.org/docs/Signing_a_Web_Widget/, instead of the following textual intercourse:
hendry@x61 ~$ cd /tmp hendry@x61 tmp$ git clone git://git.webvm.net/wgtqa Initialized empty Git repository in /tmp/wgtqa/.git/ remote: Counting objects: 2629, done. remote: Compressing objects: 100% (2056/2056), done. remote: Total 2629 (delta 1539), reused 586 (delta 235) Receiving objects: 100% (2629/2629), 694.33 KiB | 220 KiB/s, done. Resolving deltas: 100% (1539/1539), done. hendry@x61 tmp$ cd wgtqa/xmldsig/ hendry@x61 xmldsig$ ls dsakey.p12 keys rsakey.p12 sign-widget.sh validate-widget-signature.sh helloworld Makefile signing-template.sh strip-signatures.sh xmldsig.rnc hendry@x61 xmldsig$ make sign rm -f helloworld.wgt rm -f example* zip -jr helloworld.wgt helloworld/ adding: index.html (deflated 12%) adding: config.xml (deflated 15%) ./sign-widget.sh --pkcs12 /tmp/wgtqa/xmldsig/rsakey.p12 --pwd secret helloworld.wgt Key type rsa Archive: helloworld.wgt inflating: /tmp/.6129/helloworld/index.html inflating: /tmp/.6129/helloworld/config.xml Do you wish to add author-signature.xml?y Do you wish to add signature1.xml?y Do you wish to add signature2.xml?n adding: index.html (deflated 12%) adding: author-signature.xml (deflated 50%) adding: signature1.xml (deflated 52%) adding: config.xml (deflated 15%) Signed /tmp/wgtqa/xmldsig/helloworld.wgt hendry@x61 xmldsig
For purposes of a demonstration I've signed the widget twice, once as an
author-signature.xml and once as a distributor
Typically you would only sign it once in the capacity of just an author or just a distributor, with your own key. To generate your own self-signed key look at the example.p12 target in the Makefile.
Verifying or validating a widget
Since we are using test self-signed keys and not chaining to a root, we are strictly speaking not verifying a widget, we are validating its signatures instead.
If you run
make validate you'll should see something like:
./validate-widget-signature.sh --pkcs12 /tmp/wgtqa/xmldsig/rsakey.p12 --pwd secret helloworld.wgt Archive: helloworld.wgt inflating: /tmp/.13485/index.html inflating: /tmp/.13485/author-signature.xml inflating: /tmp/.13485/signature1.xml inflating: /tmp/.13485/config.xml ./author-signature.xml Signature method RSA if xmlsec1 verify --pkcs12 /tmp/wgtqa/xmldsig/rsakey.p12 --pwd secret ./author-signature.xml func=xmlSecOpenSSLX509StoreVerify:file=x509vfy.c:line=360:obj=x509-store:subj=X509_verify_cert:error=4:crypto library function failed:subj=/C=GB/ST=Surrey/L=Guildford/CN=test.webvm.net;err=18;msg=self signed certificate func=xmlSecOpenSSLX509StoreVerify:file=x509vfy.c:line=408:obj=x509-store:subj=unknown:error=71:certificate verification failed:err=18;msg=self signed certificate OK SignedInfo References (ok/all): 3/3 Manifests References (ok/all): 0/0 VALID SIGNATURE: ./author-signature.xml dsp:Identifier 9f53f8e6-acf0-11de-aa47-0016d3ccf4f1 ./signature1.xml Signature method RSA if xmlsec1 verify --pkcs12 /tmp/wgtqa/xmldsig/rsakey.p12 --pwd secret ./signature1.xml func=xmlSecOpenSSLX509StoreVerify:file=x509vfy.c:line=360:obj=x509-store:subj=X509_verify_cert:error=4:crypto library function failed:subj=/C=GB/ST=Surrey/L=Guildford/CN=test.webvm.net;err=18;msg=self signed certificate func=xmlSecOpenSSLX509StoreVerify:file=x509vfy.c:line=408:obj=x509-store:subj=unknown:error=71:certificate verification failed:err=18;msg=self signed certificate OK SignedInfo References (ok/all): 4/4 Manifests References (ok/all): 0/0 VALID SIGNATURE: ./signature1.xml dsp:Identifier a129383e-acf0-11de-b067-0016d3ccf4f1
validates the widget in one of two ways. It can try validate the
SignatureValue using a key you provide, e.g.
/tmp/wgtqa/xmldsig/rsakey.p12 in this case.
Or it can try extract the public key from the X509Certificate which can get embedded within the signature.
So in practice a widget verification would be:
- Extracting out the public key from the Keyinfo-X509Data-X509Certificate part
- Checking the hashed widget contents against each referenced resources (SignedInfo)
- Canonicalising that SignedInfo and then using that public key to check the SignatureValue
- Then verifying the key is correctly chained up to a root certificate you trust
In fact I have a validation Web service that does the first 3 steps at http://test.webvm.net/
Wait, there's more
What new element http://www.w3.org/TR/widgets-digsig introduces to XML
digital signature, is the SignatureProperty
which lies typically inside a
<Object Id="prop"> element. This has to be
unique and in my scripts I simply call a uuid generator.
So that's basically it. A widget can contain a single author signature and many several distributor signatures. The signatures are generated the same way with a:
- SignedInfo section which is the manifest, filenames and hashes
- KeyInfo - any details of the key
- Object bit, for identifying the signature itself (btw this gets hashed too in the SignedInfo as
I've modified a RelaxNG schema for Widget digital signatures, so you too can check the signature is correctly structured.
How do I check my widget runtime (WRT) supports signatures?
The spec stipulates that you must be notified if your widget is signed, self-signed or unsigned, on a widget runtime (WRT) claiming to support signatures.
If you widget runtime fails a test, you should report the bug! Thank you!