My favorites | English | Sign in

Google Apps APIs

Generating Keys and Certificates for Google Apps Single Sign-On Service

Amanda Surya, Google Apps APIs Team
July 2007

Contents

  1. Introduction
  2. Using OpenSSL
  3. Using Certificate Creation tool and Pvk2pfx tool in .NET
  4. Using Keytool in Java
  5. Using Java Cryptography Architecture
  6. Registering your certificate or public key with Google Apps
  7. Conclusion

Introduction

Google Apps offers the Single Sign-On (SSO) service to customers with Premier, Education, and Partners editions. The Google Apps Single Sign-On service accepts public keys and certificates generated with either the RSA or DSA algorithm. To use the service, you need to generate the set of public and private keys and an X.509 certificate that contains the public key. Once you have a public key or certificate, you would then need to register it with Google. You can do this by simply uploading the key or certificate via your Google Apps Control Panel.

The way you generate keys and certificates often depends on your development platform and programming language preference. In this article, I will show you several different ways to generate the keys and certificate needed by the Google Apps SSO service.

Using OpenSSL

Although there are many methods for creating public and private key pairs, the open-source OpenSSL tool is one of the most popular. It has been ported to all major platforms and provides a simple command-line interface for key generation.

Creating RSA Private Key

RSA private key generation with OpenSSL involves just one step:

openssl genrsa -out rsaprivkey.pem 1024

This command generates a PEM-encoded private key and stores it in the file rsaprivkey.pem. This example creates a 1024-bit key, which should work for nearly any purpose. The resulting private key should be kept secret and is used to sign and decrypt data.

To be able to use the key with the Java SSO sample code however, you need to take the following additional steps:

1. openssl rsa -in rsaprivkey.pem -pubout -outform DER -out rsapubkey.der
2. openssl pkcs8 -topk8 -inform PEM -outform DER -in rsaprivkey.pem -out rsaprivkey.der -nocrypt

Step 1 generates the public key in DER format. Step 2 generates the private key in pkcs8 and DER format. Once generated, you can use these keys (rsapubkey.der and rsaprivkey.der) in the Java SSO sample.

Note that the Java SSO sample code by default expects a DSA key pair, so with RSA keys, you would need to modify the sample code to accept RSA.

Creating DSA Private Key

DSA key generation involves two steps:

1. openssl dsaparam -out dsaparam.pem 1024
2. openssl gendsa -out dsaprivkey.pem dsaparam.pem

The first step creates a DSA parameter file, dsaparam.pem, which in this case instructs OpenSSL to create a 1024-bit key in Step 2. The dsaparam.pem file is not itself a key, and can be discarded after the public and private keys are created. The second step actually creates the private key in the file dsaprivkey.pem which should be kept secret.

To use the Java SSO sample code, you would need to export the key into a DER (binary) format. You can do so with the following steps:

1. openssl dsa -in dsaprivkey.pem -outform DER -pubout -out dsapubkey.der
2. openssl pkcs8 -topk8 -inform PEM -outform DER -in dsaprivkey.pem -out dsaprivkey.der -nocrypt

Step 1 extracts the public key into a DER format. Step 2 converts the private key into the pkcs8 and DER format. Once you've done this, you can use this public (dsapubkey.der) and private (dsaprivkey.der) key pair with the Java sample code.

Creating a Certificate

Once you have your key pair, it's easy to create an X.509 certificate. The certificate holds the corresponding public key, along with some metadata relating to the organization that created the certificate. Follow this step to create a self-signed certificate from either an RSA or DSA private key:

openssl req -new -x509 -key dsaprivkey.pem -out dsacert.pem

After you answer a number of questions, the certificate will be created and saved as dsacert.pem. This is the file you upload to Google Apps via the Control Panel when configuring SSO.

Using Microsoft Visual Studio for .NET

Microsoft Visual Studio 2005 provides utilities (in the Common7\Tools\Bin directory) which can be used to generate a certificate for use with Google Apps. Follow the steps below to create the public and private key pair and certificate in .NET:

1. makecert -r -pe -n "CN=Test Certificate" -sky exchange -sv testcert.pvk testcert.cer
2. pvk2pfx -pvk testcert.pvk -spc testcert.cer -pfx testcert.pfx

By default the RSA algorithm is used in the commands above. Step 1 uses the Certificate Creation Tool (makecert.exe) to create a self signed X.509 certificate called testcert.cer and the corresponding private key. Step 2 uses the pvk2pfx Tool (pvk2pfx.exe) to create a Personal Information Exchange (PFX) file from a CER and PVK file. The PFX contains both your public and private key.

The testcert.cer file created in Step 1 can be uploaded to Google Apps using the Control Panel; and, testcert.pfx from Step 2 can be used to create an X509Certificate2 (.NET 2.0+) instance for signing the SAML response. This is demonstrated in the ASP.NET SSO sample application.

Using Keytool in Java

Java developers can use the keytool utility found in the standard JDK to create the public/private key pair and X.509 certificate. keytool is a key and certificate management utility that allows users to administer their own public/private key pairs and associated certificates for use in authentication schemes requiring digital signatures. keytool stores keys and certificates in a "keystore" which for the default implementation is simply a file (".keystore") in the user's home directory. Private keys are guarded with passwords.

Creating DSA key pairs

1. keytool -genkey -alias dsassokey -keyalg "DSA" -keysize 1024 -validity 180
2. keytool -export -alias dsassokey -file dsasso.cer

Step 1 generates a public/private key pair with size 1024 and validity of 180 days using the DSA algorithm. Step 2 generates an X.509 certificate ("dsasso.cer") from the public key. You then upload dsasso.cer to Google Apps using the Control Panel.

Creating RSA key pairs

1. keytool -genkey -alias rsassokey -keyalg "RSA" -keysize 1024 -validity 180
2. keytool -export -alias rsassokey -file rsasso.cer

The above steps show how you can generate the same pair of keys and certificate but using the RSA algorithm. As in the DSA example, you then upload the generated file ("rsasso.cer") to Google Apps.

You can see that generating keys and certificate is really simple using keytool. However, as I touched on earlier, to use the Java sample code, you would need to extract the raw public and private keys. There is no straightforward way to do this using the keytool utility itself. However, you can get around this limitation by running the following two simple Java programs:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.Key;
 
public class ExtractPrivateKey {
  static public void main(String[] args) {
    try {
      KeyStore ks = KeyStore.getInstance("jks");
      ks.load(new FileInputStream(".keystore"),
	      "password".toCharArray());
      Key key = ks.getKey("aliasname",
          "password".toCharArray());
	  OutputStream privateKyFileOs = new FileOutputStream("dsaprivate.key");
	  privateKyFileOs.write(key.getEncoded());
	  privateKyFileOs.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

The code above extracts the private key identified by the aliasname from the keystore and outputs it into a file called dsaprivate.key.

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;

/**
 * This class is capable of extracting a public key from a X.509 certficate 
 * and returning the PublicKey representation from a referenced byte array.
 * 
 */
public class ExtractPublicKey {
  
  // Certificate Filename (Including Path Info)
  private static final String certFilename = "cacert.pem";
    
  // Public Key Filename (Including Path Info)
  private static final String pubKeyFilename = "dsapublic.key";

  public static PublicKey generatePublicKey(byte[] encodedKey)
      throws NoSuchAlgorithmException, InvalidKeySpecException {
    
    X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(encodedKey);
    boolean isSupportedKey = false;
    KeyFactory factory;
    PublicKey retKey = null;
    
    //first try the DSA alg
    try {
      factory = KeyFactory.getInstance("DSA");
      retKey = factory.generatePublic(pubSpec);
      isSupportedKey = true;
    } catch (InvalidKeySpecException e) {
      System.out.println("Could not create DSA Public Key: " + e.toString());      
    }
    
    //if DSA didnt work, then try RSA    
    if (!isSupportedKey) {
      try {
        factory = KeyFactory.getInstance("RSA");
        retKey = factory.generatePublic(pubSpec);
        isSupportedKey = true;
      } catch (InvalidKeySpecException e) {
        System.out.println("Could not create RSA Public Key: " + e.toString());
      }      
    }

    // if not DSA or RSA
    if (!isSupportedKey) {
      throw new InvalidKeySpecException("Unsupported key spec: Not RSA or DSA");
    }
    
    return retKey;
  }   
  
  public static void main(String [] args) {
    
    try {
      
      InputStream certFileIs = new FileInputStream(certFilename);
      CertificateFactory cf = CertificateFactory.getInstance("X509");
      X509Certificate cert = 
          (X509Certificate) cf.generateCertificate(certFileIs);        
      OutputStream publicKyFileOs = new FileOutputStream(pubKeyFilename);
      publicKyFileOs.write(cert.getPublicKey().getEncoded());
      publicKyFileOs.close();
      
    } catch (IOException e) {
      e.printStackTrace();       
    } catch (CertificateException e) {
      e.printStackTrace();
    }
    
  }
}

The code above extracts the public key from the X.509 certificate and outputs it into a file called dsapublic.key.

Using Java Cryptography Architecture

Java Cryptography Architecture (JCA) provides core classes and interfaces to generate and manipulate security properties. The JCA encompasses the parts of the Java 2 SDK Security API related to cryptography. Using this API, you can easily generate public and private key pairs in the desired algorithm. Let me show you a sample code that creates DSA or RSA keys to be used with the Google Apps SSO service.

Creating public and private key pair

import java.io.*;
import java.security.*;

public class KeyGenDSA {

  public static void main(String[] args) {
	try {
   	  KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", "SUN");
	  SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
	  keyGen.initialize(1024, random);

	  KeyPair pair = keyGen.generateKeyPair();
	  PrivateKey priv = pair.getPrivate();
	  PublicKey pub = pair.getPublic();

	  byte[] encPriv = priv.getEncoded();
	  FileOutputStream privfos = new FileOutputStream("DSAPrivateKey.key");
	  privfos.write(encPriv);
	  privfos.close();

	  byte[] encPub = pub.getEncoded();
	  FileOutputStream pubfos = new FileOutputStream("DSAPublicKey.key");
	  pubfos.write(encPub);
	  pubfos.close();

   } catch (Exception e) {
	 e.printStackTrace();
   }
  }
}

The code above uses the KeyPairGenerator to create a pair of DSA keys. The generated keys will be in binary format and are output into individual files. Once you have the keys, you can register the public key with Google Apps and use the private key to sign your SAMLResponse. To generate a pair of RSA keys instead of DSA, all you need to do is to replace "DSA" in the code with "RSA."

Registering your certificate or public key with Google Apps

Once you have done the tricky part of generating keys and certificates, the next part is really simple. To register your certificate or public key with Google Apps, you need to go to your Google Apps Control Panel http://www.google.com/a/yourdomainname.com and log in as an administrator. Select Advanced Tools, then Set up single sign-on (SSO), and fill in all the fields on the page:

Google Apps Control Panel showing SSO settings page

Sign-in page URL: This is the URL Google will redirect to when your domain end users try to access Google Apps.

Sign-out page URL: This is the URL Google will redirect to when your domain end users log out from Google Apps.

Change Password URL: This is the URL Google will redirect to when your domain end users try to change their passwords within Google Apps.

Verification Certificate: This is where you upload your X.509 certificate containing the public key. The binary public key file itself can be uploaded in place of a certificate.

Make sure you select the 'Enable Single Sign-on' check box. Then press the 'Save Changes' button to complete the process.

Conclusion

This brief tutorial has illustrated how you can generate DSA and RSA keys and create certificates to be used with the Google Apps SSO service. I've only scratched the surface with these examples. There are certainly many more ways to generate the keys and certificate you need. The methods shown here represent some of the more popular ones. If you'd like more information on each of the tools, check out the list of resources below.

Tools and sample code covered in this article:

Related knowledge base items:

If you have questions or suggestions, I'd enjoy hearing from you. Hop to the Google Apps APIs Help Forum and start posting.