After figuring out the right way to programmatically set the value of a file upload box in Firefox (http://kerneltrap.org/node/65337), I went to create a signed script. But, it was not that easy since there was no step-by-step instruction to do just that. Therefore, after solving some problems, I came up with a step-by-step instruction.
From my Computer Security class, I know that signing has something to do with public key cryptography and digital certificate. I am familiar with public key cryptography and know that GNU Privacy Guard can create a public-private key pair. But, how to create a digital certificate? So, I looked at http://en.wikipedia.org/wiki/Public_key_certificate and found interesting information: on GNU/Linux systems, one can use OpenSSL to create a digital certificate. Before going on further, I contributed a diagram illustrating how digital certificate works under the title "Diagram of an example usage of digital certificate" since "Those that know, do. Those that understand, teach."
Since a digital certificate is authorized by a Certificate Authority, I created my own CA with the following steps:
~$ mkdir my-ca
~$ cd my-ca
~/my-ca$ /usr/lib/ssl/misc/CA.pl -newca
CA certificate filename (or enter to create) [PRESS ENTER]
Making CA certificate ...
Generating a 1024 bit RSA private key
.++++++
..........++++++
writing new private key to './demoCA/private/cakey.pem'
Enter PEM pass phrase: [THIS IS PASSPHRASE FOR MY CA]
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:id
State or Province Name (full name) [Some-State]:Jawa Tengah
Locality Name (eg, city) []:Surakarta
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Eus Computer Club
Organizational Unit Name (eg, section) []:Software Development Section
Common Name (eg, YOUR name) []:Certificate Authority of Eus Computer Club
Email Address []:ca@dev.euscomputerclub.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem: [ENTER THE PASSPHRASE OF MY CA]
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number:
b5:3d:69:c3:4c:bd:d6:84
Validity
Not Before: Jul 24 13:59:11 2010 GMT
Not After : Jul 23 13:59:11 2013 GMT
Subject:
countryName = id
stateOrProvinceName = Jawa Tengah
organizationName = Eus Computer Club
organizationalUnitName = Software Development Section
commonName = Certificate Authority of Eus Computer Club
emailAddress = ca@dev.euscomputerclub.com
X509v3 extensions:
X509v3 Subject Key Identifier:
4C:A5:43:94:7E:A8:BA:E4:B0:74:83:9E:63:69:30:B0:0C:79:FB:61
X509v3 Authority Key Identifier:
keyid:4C:A5:43:94:7E:A8:BA:E4:B0:74:83:9E:63:69:30:B0:0C:79:FB:61
DirName:/C=id/ST=Jawa Tengah/O=Eus Computer Club/OU=Software Development Section/CN=Certificate Authority of Eus Computer Club/emailAddress=ca@dev.euscomputerclub.com
serial:B5:3D:69:C3:4C:BD:D6:84
X509v3 Basic Constraints:
CA:TRUE
Certificate is to be certified until Jul 23 13:59:11 2013 GMT (1095 days)
Write out database with 1 new entries
Data Base Updated
Now that my CA had been created, the next step was to make Firefox trust my CA by going to Edit -> Preferences -> Advanced tab -> Encryption tab -> View Certificates -> Authorities tab -> Import. Then, I selected cacert.pem from ~/my-ca/demoCA/. By checking all trust check boxes that appeared, I made Firefox trust my CA.
The next step was to create a request for a digital certificate with the following steps:
~/my-ca$ /usr/lib/ssl/misc/CA.pl -newreq Generating a 1024 bit RSA private key ..++++++ .++++++ writing new private key to 'newkey.pem' Enter PEM pass phrase: [THIS IS PASSPHRASE FOR BEACH SOFTWARE HOUSE CERTIFICATE] Verifying - Enter PEM pass phrase: ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:id State or Province Name (full name) [Some-State]:Bali Locality Name (eg, city) []:Nusa Dua Organization Name (eg, company) [Internet Widgits Pty Ltd]:Beach Software House Organizational Unit Name (eg, section) []:Development Team Common Name (eg, YOUR name) []:Eus Email Address []:eus@beachsoftwarehouse.com Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Request is in newreq.pem, private key is in newkey.pem
Now I needed to ask my CA to sign the certificate request. Before that, however, I needed to adjust the configuration file of OpenSSL "/etc/ssl/openssl.cnf" so that my CA would entitle me to sign digital object. So, I looked at the value of default_ca under [ca] section. Since the value is CA_default, I looked at the value of x509_extensions under [CA_default] section. Since the value is usr_cert, I uncommented "nsCertType = client, email, objsign" under [usr_cert] section. Once I enabled my CA to entitle me to sign digital object, I made my CA sign my certificate request with the following steps.
~/my-ca$ /usr/lib/ssl/misc/CA.pl -sign
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem: [THIS IS PASSPHRASE OF MY CA]
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number:
b5:3d:69:c3:4c:bd:d6:85
Validity
Not Before: Jul 24 14:22:12 2010 GMT
Not After : Jul 24 14:22:12 2011 GMT
Subject:
countryName = id
stateOrProvinceName = Bali
localityName = Nusa Dua
organizationName = Beach Software House
organizationalUnitName = Development Team
commonName = Eus
emailAddress = eus@beachsoftwarehouse.com
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Cert Type:
SSL Client, S/MIME, Object Signing
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
84:9A:35:2A:C5:E4:D9:7D:E1:48:A6:35:41:C3:C0:05:E5:0F:4A:AA
X509v3 Authority Key Identifier:
keyid:4C:A5:43:94:7E:A8:BA:E4:B0:74:83:9E:63:69:30:B0:0C:79:FB:61
Certificate is to be certified until Jul 24 14:22:12 2011 GMT (365 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
Signed certificate is in newcert.pem
[CAUTION]
You have to comment "nsCertType = client, email, objsign" again in openssl.cnf if you are creating a new CA. If you don't, the CA root certificate will be treated as invalid by signtool with the error message below and you won't be able to sign any script.
~/my-ca$ signtool -l -d signtool-db/
Object signing certificates
---------------------------------------
Eus - Eus Computer Club
Issued by: Certificate Authority of Eus Computer Club - Eus Computer Club
Expires: Sun Jul 24, 2011
++ Error ++ THIS CERTIFICATE IS NOT VALID (Certificate Authority certificate invalid)
---------------------------------------
For a list including CA's, use "signtool -L"
Now I needed to get the tool to sign my JavaScript file: sudo aptitude install libnss3-tools. Before signtool would able to sign any file, I needed to supply signtool with my digital certificate along with my private key, which will eventually be used for signing. But before that, I needed to store my digital certificate and my private key in PKCS12 format with the following steps based on the information that signtool can only import digital certificate and the private key if they are packed in PKCS12 format (http://groups.google.com/group/mozilla.dev.tech.crypto/browse_thread/thr...).
~/my-ca$ openssl pkcs12 -export -inkey newkey.pem -in newcert.pem -out beachsoftwarehouse.pkcs12 Enter pass phrase for newkey.pem: [THIS IS PASSPHRASE OF BEACH SOFTWARE HOUSE CERTIFICATE] Enter Export Password: [THIS IS PASSPHRASE FOR BEACH SOFTWARE HOUSE PKCS12 FILE] Verifying - Enter Export Password:
Since signtool also needed the certificate of the CA to be present before it is willing to sign anything with Beach Software House's private key, I needed to export my CA digital certificate without the private key in PKCS12 format as follows.
~/my-ca$ openssl pkcs12 -export -out ca.pkcs12 -in demoCA/cacert.pem -nokeys Enter Export Password: [THIS IS PASSPHRASE FOR CA PKCS12 FILE] Verifying - Enter Export Password:
Before importing the PKCS12 file, I needed to create the signtool DB with the following steps (tools in libnss3-tools have no man page; the complete manuals can be read by using -H switch as in "signtool -H").
~/my-ca$ mkdir signtool-db ~/my-ca$ certutil -N -d signtool-db Enter a password which will be used to encrypt your keys. The password should be at least 8 characters long, and should contain at least one non-alphabetic character. Enter new password: [THIS IS PASSPHRASE FOR SIGNTOOL DB] Re-enter password:
Now I could import the PKCS12 file of Beach Software House into signtool DB with the following steps.
~/my-ca$ pk12util -i beachsoftwarehouse.pkcs12 -d signtool-db Enter Password or Pin for "NSS Certificate DB": [THIS IS PASSPHRASE OF SIGNTOOL DB] Enter password for PKCS12 file: [THIS IS PASSPHRASE OF BEACH SOFTWARE HOUSE PKCS12 FILE] pk12util: no nickname for cert in PKCS12 file. pk12util: using nickname: Eus - Eus Computer Club pk12util: PKCS12 IMPORT SUCCESSFUL
At this point, signtool will refuse to use the certificate and private key of Beach Software House to sign anything because signtool cannot verify its certificate authority as demonstrated below.
~/my-ca$ signtool -l -d signtool-db/
Object signing certificates
---------------------------------------
Eus - Eus Computer Club
Issued by: E=ca@dev.euscomputerclub.com,CN=Certificate Authority of Eus Computer Club,OU=Software Development Section,O=Eus Computer Club,ST=Jawa Tengah,C=id
Expires: Sun Jul 24, 2011
++ Error ++ THIS CERTIFICATE IS NOT VALID (unknown issuer)
---------------------------------------
For a list including CA's, use "signtool -L"
So, I imported the PKCS12 file of my CA as follows.
~/my-ca$ pk12util -i ca.pkcs12 -d signtool-db/ Enter Password or Pin for "NSS Certificate DB": [THIS IS PASSPHRASE OF SIGNTOOL DB] Enter password for PKCS12 file: [THIS IS PASSPHRASE OF CA PKCS12 FILE] pk12util: PKCS12 IMPORT SUCCESSFUL
At this point although signtool can verify the certificate authority, signtool still cannot trust the CA and so regarded the CA certificate as invalid as shown below.
~/my-ca$ signtool -l -d signtool-db/
Object signing certificates
---------------------------------------
Eus - Eus Computer Club
Issued by: Certificate Authority of Eus Computer Club - Eus Computer Club
Expires: Sun Jul 24, 2011
++ Error ++ THIS CERTIFICATE IS NOT VALID (Certificate Authority certificate invalid)
---------------------------------------
For a list including CA's, use "signtool -L"
Therefore, I needed to tell signtool that I trust the CA as follows.
~/my-ca$ certutil -d signtool-db/ -M -n 'Certificate Authority of Eus Computer Club - Eus Computer Club' -t 'TC,C,C'
Next I created an HTML file containing a script to programmatically set the value of a file upload box as follows.
~/my-ca$ mkdir script
~/my-ca$ cat >> script/index.html
<html>
<head>
<title>Automatic Upload</title>
<script type="text/javascript">
function setFile()
{
try {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
netscape.security.PrivilegeManager.enablePrivilege("UniversalFileRead");
document.getElementById('filebox').value = '/etc/passwd';
} catch (err) {
alert('Permission denied: ' + err);
}
}
</script>
</head>
<body>
<input id="filebox" type="file" size="50"/>
<input type="button" value="Set file to upload" onclick="setFile()"/>
</body>
Then I signed the file as follows.
~/my-ca$ signtool -k 'Eus - Eus Computer Club' -d signtool-db/ -Z script.jar script/ Generating script//META-INF/manifest.mf file.. --> index.html adding script//index.html to script.jar...(deflated 41%) Generating zigbert.sf file.. Enter Password or Pin for "NSS Certificate DB": adding script//META-INF/manifest.mf to script.jar...(deflated 15%) adding script//META-INF/zigbert.sf to script.jar...(deflated 27%) adding script//META-INF/zigbert.rsa to script.jar...(deflated 29%) tree "script/" signed successfully
Now I tried to see what would happen if I simply opened ~/my-ca/script/index.html in Firefox and executed the JavaScript code. For this, I set "javascript.options.showInConsole" to true in "about:config" to be able to see any error message in the Error Console (Ctrl+Shift+J). Well, I got the following error message in the Error Console if I removed the exception handling from index.html:
Error: A script from "file:///home/eus/my-ca/script/index.html" was denied UniversalXPConnect privileges. Source File: file:///home/eus/my-ca/script/index.html Line: 7
If I didn't remove the exception handler, I got the following alert:
Permission denied: Error: A script from "file:///home/eus/my-ca/script/index.html" was denied UniversalXPConnect privileges
Now if I didn't uncomment "nsCertType = client, email, objsign" in openssl.cnf before making my CA signed the certificate request of Beach Software House, first upon executing "/usr/lib/ssl/misc/CA.pl -sign", the certificate details would miss the following lines.
Netscape Cert Type:
SSL Client, S/MIME, Object Signing
Second, "signtool -l -d signtool-db" would return the following message.
Object signing certificates --------------------------------------- You don't appear to have any object signing certificates. --------------------------------------- For a list including CA's, use "signtool -L"
Third, forcing my way to sign the script with "signtool -k 'Eus - Eus Computer Club' -d signtool-db/ -Z script.jar script" would throw out the following message.
Generating script/META-INF/manifest.mf file.. --> index.html adding script/index.html to script.jar...(deflated 41%) Generating zigbert.sf file.. Enter Password or Pin for "NSS Certificate DB": signtool: PROBLEM signing data (Certificate not approved for this operation) the tree "script" was NOT SUCCESSFULLY SIGNED
Fourth, I could for force signtool to be willing to sign the script with "certutil -M -n 'Eus - Eus Computer Club' -t 'P,P,P' -d signtool-db/" to tell signtool that I trusted Beach Software House certificate for signing object. But, I got the following message in the Error Console upon accessing the index.html in the JAR file in URL "jar:file:///home/eus/my-ca/script.jar!/index.html".
Signature Verification Error: the signature on index.html is invalid because the digital signature (*.RSA) file is not a valid signature of the signature instruction file (*.SF).
That certainly is not a very helpful message to say that a digital certificate lacks the extension that entitles it to sign a digital object.
To conclude, following the correct steps enables me to programmatically set the value of a file upload box by accessing index.html at "jar:file:///home/eus/my-ca/script.jar!/index.html" after answering allow to the two dialogs that appeared. Below is the picture of one of the dialog box.

PS: previously the system Firefox in my GNU/Linux Ubuntu Jaunty would silently deny index.html from obtaining additional privilege when I accessed index.html by "file:///home/eus/my-ca/script/index.html" so that I had to see the denial message in the error console. But, after some system updates, the system Firefox now treats all scripts accessed through "file://" as if they are signed (i.e., accessing file:///home/eus/my-ca/script/index.html directly pops the dialog to grant additional privilege instead of silently denying the script request as before).
WiSHlsJoRPbneAb
3oaU1W oxugtegtkspl, [url=http://zflpfihhachs.com/]zflpfihhachs[/url], [link=http://isngpitqiavt.com/]isngpitqiavt[/link], http://wxaplbmmimho.com/