Xml signature Tutorials
Introduction
This document contains 3 tutorials
- Xml signing with certificate
- Xml signing without certificate
- Widget signing
An xml signature can be used to sign any file type.
We support a parts of the xml digital signature spec.
We support the (not finished) widget digital signature spec.
To sign files you need to following third party tools
- Apache xml security: download apache security source code from here. We need the tool 'templatesign' from this package
- openssl, or any other tools capable to of generating PKI keys and certificates. In this tutorial we use openssl.
To verify the signatures, use the api in modules/libcrypto/include/CryptoXmlSignature.h
XML signing tutorial (with certificate)
An xml signature bundled with a certificate is used when you want to protect the users from evil code generated by a third party.
If you want to protect our code or config files from being tampered by the opera user, you should sign without a certificate, and instead hardcode the public key in memory (See tutorial below).
Create a private key
First generate a private_key which will be used to sign the files:
openssl genrsa -des3 -out cakey.pem 4096
Create a self-signed CA certificate
openssl req -new -x509 -key cakey.pem -out cacert.pem
NOTE Only do this for testing. In real life you should use one of the certificates allready installed in Opera.
Install cakey.pem in the browser.
This can be done using desktop opera 9.5:
Go to preferences->Advanced->Security->Manage Certificates->Authorities->Import.
Choose *.pem type, in import cacert.pem
To install the certificate into a mobile phone, copy ~/.opera/opcacrt6.dat from your desktop opera into the device.
Create a signer certificate
openssl genrsa -des3 -out privsignerkey.pem 4096
When prompted enter a *very* strong password
Create a request for a certificate signed by CA:
openssl req -new -key privsignerkey.pem -out certificate_request.csr
Handle the request using the previous created CA certificate:
openssl x509 -req -days 365 -in certificate_request.csr -CA cacert.pem -CAkey cakey.pem -set_serial 01 -out signercert.pem
Signing files
Template file
Save this file to signature_template.xml. Edit the file and create one reference element per file to be signed.
<?xml version="1.0" encoding="UTF-8"?>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod
Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod
Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<Reference URI="any_signed_file1.extension">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue> </DigestValue>
</Reference>
<Reference URI="dir/any_signed_file2.extension">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue> </DigestValue>
</Reference>
<Reference URI="dir/any_signed_file3.extension">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue> </DigestValue>
</Reference>
</SignedInfo>
<SignatureValue> </SignatureValue>
</Signature>
Important: The spaces in the values of the <DigestValue> and <SignatureValue> tags are important. The templatesign tool will replace the spaces with the correct digests and signature.
Save the file in a directory so that the relative paths given by <Reference URI="some_path/some_file> holds.
Signing
Sign with:
templatesign -r private.pem <The password given to openssl genrsa> -x signercert.pem signature_template.xml > signature.xml
templatesign comes from the apache xml security package.
signature_template.xml can now be discarded.
Check signature
static OP_STATUS XmlSignature::VerifyXmlSignature(OpString &signer_id, VerifyError &reason, const uni_char *signed_files_base_path, const uni_char *signature_xml_file, BOOL ignore_certificate = FALSE, const unsigned char *public_key = 0, unsigned long key_len = 0);
with ignore_certificate = FALSE
XML signing tutorial (without certificate)
You need the following addidational tools on linux
- hexdump, --""--
- base64, --""--
If you want to protect our code or config files from being tampered by opera user, you should sign without certificate, and instead hard code the public key in memory.
The reason is that the certificate system is not meant for protecting our files from the user.
In this case the user can install his own self signed CA certificate and then sign the config.
Create a private key
First generate a private_key which will be used to sign the files:
openssl genrsa -des3 -out private.pem 4096
Generate the public key
Get the public key from private.pem:
openssl rsa -in private.pem -out public.pem -pubout
Convert to binary
Edit public_pem, remove linebreaks and the first and last line (only keep the base64 encoded string).
Next, convert the edited file to binary:
base64 -d public.pem > public.bin
Convert to a C char array
Generate a char array to put in source code. Use this to verify signed files.
hexdump -e '8/1 "0x%02x, " "\n"' public.bin > public.hexdump
Signing files
Template file
Save this file to signature_template.xml. Edit the file and create one reference element per file to be signed.
<?xml version="1.0" encoding="UTF-8"?>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod
Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod
Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<Reference URI="any_signed_file1.extension">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue> </DigestValue>
</Reference>
<Reference URI="dir/any_signed_file2.extension">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue> </DigestValue>
</Reference>
<Reference URI="dir/any_signed_file3.extension">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue> </DigestValue>
</Reference>
</SignedInfo>
<SignatureValue> </SignatureValue>
</Signature>
Important: The spaces in the values of the <DigestValue> and <SignatureValue> tags are important. The templatesign tool will replace the spaces with the correct digests and signature.
Save the file in a directory so that the relative paths given by <Reference URI="some_path/some_file> holds.
Signing
Sign with:
templatesign -r private.pem <The password given to openssl genrsa> signature_template.xml > signature.xml
templatesign comes from the apache xml security package.
signature_template.xml can now be discarded.
Check signature
Use
static OP_STATUS XmlSignature::VerifyXmlSignature(OpString &signer_id, VerifyError &reason, const uni_char *signed_files_base_path, const uni_char *signature_xml_file, BOOL ignore_certificate = FALSE, const unsigned char *public_key = 0, unsigned long key_len = 0);
with
ignore_certificate = TRUE,
public_key = { the char array from public.hexdump },
key_len = the file size of public.bin (should be the same as the length of the char array public_key }
Widget signing tutorial
Needed tools
The signer bash script modules/libcrypto/scripts/signwidget.sh will only work in linux. It should be easy, however, to create a similar script in any other script language.
The signer script uses the tool "templatesign" from apache security to sign widgets. Download source code from here.
There is also a java version of the same library here .
Follow the instructions given in this package to compile and install. Check that the tool 'templatesign' is installed in your
system.
You also need to install openssl.
In addition we have made a simple bash script (modules/libcrypto/scripts/signwidget.sh) to simplify widget signing.
Create certificates
To sign widgets with a signature that verifies in all opera instances, you need to create two certificates. One CA certificate that is installed in
all Opera instances, and one signer certificate that you use to sign the widgets. The signer certificate must be signed by the CA certificate.
Note that this tutorial is for testing only. In real life the Certificate Authority should be Verisign or similar.
Create a certificate authority
Create a private key
First create a private key for the certificate authority (CA) :
openssl genrsa -des3 -out cakey.pem 4096
When prompted enter a *very* strong password
Create a self-signed CA
Next, create a self-signed CA certificate:
openssl req -new -x509 -key cakey.pem -out cacert.pem
import the Ca cert into Opera
Install cakey.pem in the browser. This can be done using desktop opera 9.5:
Go to preferences->Advanced->Security->Manage Certificates->Authorities->Import.
Choose *.pem type, in import cacert.pem
To install the certificate into a mobile phone, copy ~/.opera/opcacrt6.dat from your desktop opera into the device.
Create a signer certificate
Create a private key
openssl genrsa -des3 -out privsignerkey.pem 4096
When prompted enter a *very* strong password
Create a public certificate
Create a request for a certificate signed by CA:
openssl req -new -key privsignerkey.pem -out certificate_request.csr
Handle the request using the previous created CA certificate:
openssl x509 -req -days 365 -in certificate_request.csr -CA cacert.pem -CAkey cakey.pem -set_serial 01 -out signercert.pem
Signing a widget
Use the bash script given in modules/libcrypto/scripts/signwidget.sh
signwidget.sh -r <rsakey> -p <rsakey password> -x <x509cert> <widgetpath>
We can now a sign a widget using the signercert.pem create above:
signwidget.sh -r privsignerkey.pem -p <rsakey password> -x signercert.pem <widgetpath>
Where <rsakey password> is the key you entered when creating privsignerkey.pem