# Xml signature Tutorials

## Introduction

This document contains 3 tutorials

1. Xml signing with certificate
2. Xml signing without certificate
3. 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