Friday, July 4, 2008

Creating your own Certificate Authority using OpenSSL

It took me a long time to put all this together, but now it seems extremely simple. I hope it comes in handy to others who are trying to setup a private CA.

There are three parts:
a) Creating a Certificate Authority
b) Setting up the Server(Tomcat)
c) Setting up the client

This article does not cover certificate revocation.

a) Creating a Certificate Authority

There are two ways to do this
- Using scripts provided by OpenSSL
- Using OpenSSL commands and creating your own directory structure

We will use the second method. So lets get started. Make sure you have downloaded and installed OpenSSL

1) Create a new Directory structure

MyCompanyCA\private

2) Goto the MyCompanyCA directory, create an RSA keypair for the CA using OpenSSL:

% openssl genrsa -des3 -out private/CA_key.pem 2048

Note down password you entered above for CA PASSWORD here _________________

3) Next, create, from the private key, the public-key certificate for your CA. To generate this self-signed certificate, use the following command:

% openssl req -new -key private/CA_key.pem -x509 -days 365 -out CA_cert.cer

This creates a public-key certificate from the private key you generated earlier. The -x509 switch indicates that we wish to generate this X.509 certificate, and the -days switch gives our generated certificate an expiration date. Since we are generating this public-key certificate for the first time, the command asks a number of questions, intended to populate the necessary X.500 information:

% openssl req -new -key private/CA_key.pem -x509 -days 365 -out CA_cert.cer
Enter pass phrase for private/CA_key.pem:
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]:CA
State or Province Name (full name) [Some-State]:Ontario
Locality Name (eg, city) []:Toronto
Organization Name (eg, company) [Internet Widgits Pty Ltd]:MyCompany Info Inc.
Organizational Unit Name (eg, section) []:SECURITY Team
Common Name (eg, YOUR name) []: Certificate Authority Created by Ash Srivastava
Email Address []: asrivastava@MyCompanyinfo.com

Note: the public-key certificate should be the only file from the two that you just generated that you should share with anyone.
That’s all you need, your CA is now setup.

b) Setting up the Server(Tomcat)

1) Goto your local tomcat directory(Ex: Tomcat 5.5)
2) Generate a private key and CSR(Certificate Signing request) using the Java keytool application. To generate an RSA keypair using keytool, use the following command:

% keytool -genkey -v -alias tomcat -keyalg RSA -keysize 2048 -keystore my_keystore.jks

This command generates an RSA keypair of size 2,048 bits, following the OpenSSL example above. However, keytool will, at the same time, also generate a Java keystore (JKS) format keystore file in which the keypair, along with a self-signed public-key certificate, is placed, giving it a shorter alias of "tomcat." Since keytool creates the X.509 certificate in this step, it asks the user for the necessary X.500 information:

% keytool -genkey -v -alias tomcat -keyalg RSA -keysize 2048 -keystore my_keystore.jks
Enter keystore password: password
What is your first and last name?
[Unknown]: localhost
What is the name of your organizational unit?
[Unknown]: SECURITY team
What is the name of your organization?
[Unknown]: MyCompany Info Inc.
What is the name of your City or Locality?
[Unknown]: Toronto
What is the name of your State or Province?
[Unknown]: Ontario
What is the two-letter country code for this unit?
[Unknown]: CA
Is CN=localhost, OU=SECURITY team, O= MyCompany Info Inc., L=Toronto, ST=Ontario, C=CA correct?
[no]: yes
Generating 2,048 bit RSA key pair and self-signed certificate (MD5WithRSA)
for: CN=localhost, OU=SECURITY team, O= MyCompany Info Inc., L=Toronto, ST=Ontario, C=CA
Enter key password for
(RETURN if same as keystore password):
[Saving my_keystore.jks]

The CN should exactly be the name of the host which this certificate will identify i.e in my case localhost. Note down password you entered above for server keystore PASSWORD here _________________

3) To generate the CSR from our new keypair using keytool, you can use the following command:

% keytool -certreq -v -alias tomcat -keystore my_keystore.jks -file tomcat_request.csr
You can now submit the resulting file to the CA for certificate issuance.

4) Using the private key/public-key certificate you generated earlier for the CA, you can sign the certificate contained in the CSR using OpenSSL. Copy tomcat_request.csr to MyCompanyCA directory, the goto MyCompanyCA directory and type the following:

% openssl x509 -req -days 365 -in tomcat_request.csr -CA CA_cert.cer -CAkey private/CA_key.pem -CAcreateserial -out tomcat.cer

This command issues a new certificate, signed by your CA, with a validity period of one year. The use of the -CAcreateserial switch enables the unique assignment of serial numbers to our issued certificates. Since this is the first certificate issued by your CA, a new file is created (demoCA/CA_cert.srl) containing the number "02," which is the next serial number to be used when the next certificate is issued (serial number "01" was used by the first certificate). Thus, when issuing subsequent certificates, you would use the following command:

% openssl x509 -req -days 365 -in new_request.csr -CA demoCA/CA_cert.cer -CAkey demoCA/private/CA_key.pem -CAserial demoDA/CA_cert.srl -out new_certificate.cer

Once your CA has issued the certificate, you can send it back to the requester for use. It's also important to keep a copy of the certificate around, just in case you need to revoke it later.

5) Send tomcat.cer and CA_cert.cer to the server and paste tomcat.cer to the server directory. (Ex: Tomcat 5.5).

Rename my_keystore.jks to keystore.key

Now add CA_cert.cer to the truststore and tomcat.cer to the keystore.

The keystoreFile is a collection of X.509 certificates one of which Tomcat will use to identify itself to Browsers. This certificate contains the DNS name of the server on which Tomcat is running which the HTTP client will have used as the servername part of the URL. It is possible to use a file that contains multiple certificates (in which case Tomcat will use the certificate stored under the alias "Tomcat" or, if that is not found, will use the first certificate it finds that also has an associated private key). However, to assure that no mistakes are made it is sensible practice to use a file that has only the one host certificate, plus of course its private key and chain of parent Certificate Authorities.

The truststoreFile is a collection of X.509 certificates representing Certificate Authorities from which Tomcat is willing to accept User certificates. Since the keystoreFile contains the CA that issued the certificate identifying the server, the truststoreFile and keystoreFile could be the same in a CAS configuration where the URL (actually the port) that uses X.509 authentication is not the well know widely recognized URL for interactive (userid/password form) login, and therefore the only CA that it trusts is the institutional internal CA.
The JKS (Java Key Store) file format is maintained by a tool provided by Sun in the /bin subdirectory of the Java Development Kit (JDK) distribution of your current version of Java. It is documented in http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/keytool.html.

Add CA_cert.cer to the truststore
% keytool --import -alias CA -keystore trustStore.jks -file CA_cert.cer
Enter keystore password: tomcat
Owner: EMAILADDRESS=asrivastava@MyCompanyinfo.com, CN=Certificate Authority Created by Ash Srivastava, OU=SECURITY Team, O=MyCompany Info Inc., L=Toronto, ST=Ontario, C=CA
Issuer: EMAILADDRESS=asrivastava@MyCompanyinfo.com, CN=Certificate Authority Created by Ash Srivastava, OU=SECURITY Team, O=MyCompany Info Inc., L=Toronto, ST=Ontario, C=CA
Serial number: 0
Valid from: Wed Jul 02 16:10:50 EDT 2008 until: Thu Jul 02 16:10:50 EDT 2009
Certificate fingerprints:
MD5: 22:15:FB:7D:3D:22:40:3E:BC:EE:FD:33:92:BF:E6:8F
SHA1: 8A:EC:45:37:8D:1F:F0:E7:B4:20:69:B9:DC:93:AC:C6:46:04:7E:7E
Trust this certificate? [no]: yes
Certificate was added to keystore

Note down password you entered above for server truststore PASSWORD here___________

Add tomcat.cer to the keystore
% keytool -import -trustcacerts -alias tomcat -file tomcat.cer -keystore keystore.key
You will be asked to provide the server keystore password here

6) Go in server.xml for tomcat and enable SSL by commenting out the 8080 connector and enabling the SSL connector and add the keystore and truststore location

server.xml's SSL section should look like the following:

connector port="8443" maxhttpheadersize="8192" maxthreads="150" minsparethreads="25" maxsparethreads="75" enablelookups="false" disableuploadtimeout="true" acceptcount="100" scheme="https" secure="true" clientauth="true" sslprotocol="TLS" keystorefile="keystore.key" keystorepass="tomcat" truststorefile="trustStore.jks" truststorepass="tomcat"

The clientAuth="want" tells Tomcat to request that the Browser provide a User certificate if one is available. If you want to force the use of User certificates, replace "want" with "true". If you specify "want" and the browser does not have a certificate, then the Webflow configuration described below will forward the request to the userid/password form.

Congratulations your server is setup now.

c) Setting up the client

1) Add CA_cert.cer to your browsers Trust Store
In Firefox, Tools->Options->View Certificates->Authorities Tab->Import
In IE, Tools->Internet options->Content tab->Certificates Button->Trusted root Certification Authorities tab -> Import

2) The client should install openSSL and should generate their private key and a CSR. Create a folder caller ClientCertificate on client computer. Go in that folder and first, you need to generate an RSA private key for the new server:

% openssl genrsa -des3 -out ash.pem 2048

Note down password you entered above for client private key PASSWORD here_________
Just as in the CA example above, this command generates a new RSA private key protected by a DES3 password.

Since you want your CA to issue the public-key certificate, enabling distributed trust by other members of the PKI, you now need to generate a certificate signing request (CSR) from your private key. Using OpenSSL, you can do so with the following command:

% openssl req -new -key ash.pem -out ash_request.csr
It is this CSR file that you can now submit to the CA for public-key certificate issuance.

3) Send ash_rquest.csr to your CA and run the following command in your CA_cert.cer directory

% openssl x509 -req -days 365 -in ash_request.csr -CA CA_cert.cer -CAkey private/CA_key.pem -CAcreateserial -out ash.cer

You will required to enter the CA private key password. Send ash.cer and CA_cer back to the client

4) Now you have ash.pem, ash.cer and CA_cert.cer in your ClientCertificate Directory
To add the client certificate to the browser it has to be in .p12 format. The following command creates a single PKCS#12 file from client certificate, its key and issuer's (CA's) certificate. -name and -caname specify PKCS#12 friendly names for client's cert and CA's cert respectively.

> openssl pkcs12 -export -in ash.cer -inkey ash.pem -certfile CA_cert.cer -out ash.p12 -name "Ash Client Cert 001" -caname "MyCompany CA"

So you have created ash.p12 file which you can go and add to you browser to identify yourself to the server.

In Firefox, Tools->Options->View Certificates->Your Certificate Tab->Import
In IE, Tools->Internet options->Content tab->Certificates Button-> Personal Tab -> Import
Now go to the server and the browser will present you with the certificate you will like to use to represent yourself to the server.

d) Extracting X509 variables from the certificate and using it in a web app.

In the servlet doPost method add the following,

java.security.cert.X509Certificate[] certs = (java.security.cert.X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
HTMLWriter.writeSSLInfo(response,certs);

Simply extract and dispay it on the page

public static void writeSSLInfo(HttpServletResponse response,
X509Certificate[] certs) throws IOException {

response.setContentType("text/html");
PrintWriter writer = response.getWriter();

writeCommonHead(writer, "Authenticate");
for (int i=0; i < style="font-weight: bold;">References
1. http://www.linux.com/feature/38315
2. http://www.ja-sig.org/wiki/display/CASUM/X.509+Certificates
3. http://www.digicert.com/ssl-certificate-installation-tomcat.htm
4. http://www.orenosv.com/orenosp/certmemo_en.txt


Wednesday, April 30, 2008

Basic Authentication: Call Java Web Service from C#

protected override System.Net.WebRequest GetWebRequest(Uri uri){
System.Net.WebRequest request = base.GetWebRequest (uri);
string username = "Test";
string password = "Test";
string auth = username + ":" + password;
byte[] binaryData = new Byte[auth.Length];
binaryData = Encoding.UTF8.GetBytes(auth);auth = Convert.ToBase64String(binaryData);
auth = "Basic " + auth;
request.Headers["AUTHORIZATION"] = auth;
return request;
}

ref: Yelei's Blog

Friday, March 7, 2008

Remote Debugging a Web Service using Eclipse and Tomcat

This is working with Tomcat 5.0.X, Eclipse 3.2, JDK 1.4.2_*

Step 1. Configure Tomcat
a) Open up the configuration GUI ("Configure Tomcat")
b) Select the Java tab
c) Into the Java Options include (substituting the correct locations)
-Xdebug
-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n
-Dcatalina.home=c:\tomcat
-Djava.endorsed.dirs=c:\tomcat\common\endorsed
-Djava.io.tmpdir=c:\tomcat
NB: These are all on separate lines, with a at each EOL
d) Select the Startup tab
e) Into the Arguments section include:
jpda
start
NB: These are all on separate lines, with a at each EOL
f) Start and Stop Tomcat completely

2. Configure Eclipse
a) While in the Java perspective select "open Debug Dialog"
b) Choose "Remote Java Application" from the tree (right click/New)
c) The defaults are all that is required.
d) Click "Debug" in the bottom corner to start it now, or Close for later

3. Debugging the Application
a) Create a breakpoint in the code
b) Click on the "Debug" (if not already debugging) (*)
c) Click on the Debug Perspective (optional)


(*) If you get an error such as "Failed to connect to remote VM. Connection Refused". This normally means that Tomcat isn't started, _or_ there is already a debugging session started via jpda. Check Tomcat is running, and check the Debug perspective to make sure that it isn't running.

Friday, February 29, 2008

Coverting Date to XMLGregorianCalendar format in java

private XMLGregorianCalendar Date2XMLDate(Date d)
throws DatatypeConfigurationException {


Calendar c = new GregorianCalendar();

c.setTime(d);
int month = c.get(Calendar.MONTH)+1;
int day = c.get(Calendar.DAY_OF_MONTH);
int year = c.get(Calendar.YEAR);
DatatypeFactory df = DatatypeFactory.newInstance();

XMLGregorianCalendar x = df.newXMLGregorianCalendarDate(year, month, day, c.getTimeZone().getOffset(d.getTime())/(60*60*1000));

return x;
}

Friday, February 8, 2008

How to add nodes to a TreeView WebBrowser control by using Visual C# .NET


Download the IE Web Controls here and follow instructions in ReadMe.txt to install

1. Add the TreeView Control to the WebForm1.aspx.
2. Click F7 and you will be in Code View

using Microsoft.Web.UI.WebControls;
....
.....
......

TreeNode head ;
TreeNode child;
private void Button1_Click(object sender, System.EventArgs e)
{
head = new TreeNode();
head.Text = "My First Tree Node";
TreeView1.Nodes.Add(head);//Adding Nodes

child = new TreeNode();
child.Text = "My second Tree Node";
head.Nodes.Add(child); //Adding Nodes


}

It is as simple as it seems, you can display objects and XML data using this.


Useful Resources:

Converting DateTime Object from .NET to XSD

if you are trying to consume a Java Web Service in .NET simply follow the instruction in Consuming a Web Service in .NET, you might run into some issues when dealing with DateTime Object. You want to make sure that the format of DateTime being sent to the Web Service(WS) is the one it expects. The WS i was working with required the DateTime in XSD format.

You can use XmlConvert or SoapDateTime class to convert the date to a string, but the problem is the the format they return is "2007-12-14T10:37:00.0000000-05:00" and the actual XSD format is "2007-12-14T10:37:00.000-05:00". There are 4 extra zeros. So i wrote a simple method to convert .NET DateTime Object to XSD format.

public String toXSDDateFormat(DateTime d)
{
String strD = XmlConvert.ToString(d);
String d1 = strD.Substring(0,strD.LastIndexOf(".")+4);
String d2 = strD.Substring(strD.LastIndexOf("-"),strD.Length -
strD.LastIndexOf("-"));

return d1+d2;
}

Hope this helps !!

Thursday, February 7, 2008

Consuming a Web Service in .NET

1. Get the WSDL location(http://localhost:8080/als-2.2.1/als?wsdl), make sure the XSD location in it is correct(http://localhost:8080/als-2.2.1/als?xsd=1)
2. Use wsdl.exe. In the Command Window,
C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin>wsdl http://localhost:8080/als-2.2.1/als?wsdl

If you get errors:
Microsoft (R) Web Services Description Language Utility
[Microsoft (R) .NET Framework, Version 1.1.4322.573]
Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.

Error: URI formats are not supported.

If you would like more help, please type "wsdl /?".

Simply save the .wsdl and .xsd file to the local drive and run
C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin>wsdl als.wsdl

If all goes well you will see
C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin>wsdl als.wsdl
Microsoft (R) Web Services Description Language Utility
[Microsoft (R) .NET Framework, Version 1.1.4322.573]
Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.

Writing file 'C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin\AL
SService.cs'.

3. Now add this file(ALSService.cs) to you current webproject and then add the Web Service to your project.
4. To refer to the the Web Service initiate an instance in WebForm1 and you can declare the DataTypes in ALSService in your Webform.

public class WebForm1 : System.Web.UI.Page
{
ALSService als = new ALSService();
..................
//calling methods
als.methodName()
...........
...........
}

Congratulations you are now ready to consume the Web Service.

Resources:
Using wsdl.exe

Registering ASP.NET on IIS after installing the .NET Framework

If you install the .NET Framework on a system that has IIS already installed, IIS is automatically configured to handle requests to ASP.NET pages, and to redirect the execution to the ASP.NET runtime. However, it may happen that you installed the framework on a Windows 2000 Professional system where IIS was not already present, and just later decided to add IIS. Registering ASP.NET on IIS is not just a matter of associating the various .aspx, .asmx, .axd, .ashx and the other ASP.NET extensions to the aspnet_isapi.dll ISAPI, more has to be done to create the ASP.NET account and to set it for ASP.NET requests, register the ISAPI itself and other stuff. Doing all this manually can be a difficult operation, and requires a good understanding of many details. Fortunately there is an utility, shipped with the .NET Framework but not documented, that can take care of these configuration chores for you. The utility is aspnet_regiis.exe, it is located under %WindowsDir%\Microsoft.NET\Framework\vx.y.zzzz\ and you should call it with the -i parameter: aspnet_regiis.exe -i