Root certificate and signing certificates

- Add method to generate a Root Certificate (allowing a chain of 1)
- Add method to sign a provided "certificate" - Really if provided with
  a public key, generate a chain of a new certificate signed with the
  Root certificate
- Changed certificate dates from -30 days and +10 years from day it was
  generated
- Changed email in certificate

Change-Id: I405417d0b3c495d8bda83d4ca21a803c4667bbb6
diff --git a/java/src/com/google/polo/ssl/CsrUtil.java b/java/src/com/google/polo/ssl/CsrUtil.java
new file mode 100644
index 0000000..d5ff7bc
--- /dev/null
+++ b/java/src/com/google/polo/ssl/CsrUtil.java
@@ -0,0 +1,156 @@
+package com.google.polo.ssl;
+
+import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
+import org.bouncycastle.asn1.x509.BasicConstraints;
+import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
+import org.bouncycastle.asn1.x509.GeneralName;
+import org.bouncycastle.asn1.x509.GeneralNames;
+import org.bouncycastle.asn1.x509.KeyPurposeId;
+import org.bouncycastle.asn1.x509.KeyUsage;
+import org.bouncycastle.asn1.x509.X509Extensions;
+import org.bouncycastle.asn1.x509.X509Name;
+import org.bouncycastle.x509.X509V3CertificateGenerator;
+import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
+import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;
+
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * Utility class to generate X509 Root Certificates and Issue X509 Certificates signed by a root
+ * Certificate.
+ */
+public class CsrUtil {
+    private static final String SIGNATURE_ALGORITHM = "SHA256WithRSAEncryption";
+    private static final String EMAIL = "android-tv-remote-support@google.com";
+    private static final int NOT_BEFORE_NUMBER_OF_DAYS = -30;
+    private static final int NOT_AFTER_NUMBER_OF_DAYS = 10 * 365;
+
+    /**
+     * Generate a X509 Certificate that should be used as an authority/root certificate only.
+     *
+     * This certificate shouldn't be used for communications, only as an authority as it won't have
+     * the correct flags.
+     *
+     * @param rootName Common Name used in certificate.
+     * @param rootPair Key Pair used to signed the certificate
+     * @return
+     * @throws GeneralSecurityException
+     */
+    public static X509Certificate generateX509V3AuthorityCertificate(String rootName,
+            KeyPair rootPair)
+            throws GeneralSecurityException {
+        Calendar calendar = Calendar.getInstance();
+        calendar.add(Calendar.DAY_OF_YEAR, NOT_BEFORE_NUMBER_OF_DAYS);
+        Date notBefore  = new Date(calendar.getTimeInMillis());
+        calendar.add(Calendar.DAY_OF_YEAR, NOT_AFTER_NUMBER_OF_DAYS);
+        Date notAfter = new Date(calendar.getTimeInMillis());
+
+        BigInteger serialNumber = BigInteger.valueOf(Math.abs(System.currentTimeMillis()));
+
+        return generateX509V3AuthorityCertificate(rootName, rootPair, notBefore, notAfter, serialNumber);
+    }
+
+
+    @SuppressWarnings("deprecation")
+    static X509Certificate generateX509V3AuthorityCertificate(String rootName,
+            KeyPair rootPair, Date notBefore, Date notAfter, BigInteger serialNumber)
+            throws GeneralSecurityException {
+        X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+        X509Name dnName = new X509Name(rootName);
+
+        certGen.setSerialNumber(serialNumber);
+        certGen.setIssuerDN(dnName);
+        certGen.setSubjectDN(dnName);
+        certGen.setNotBefore(notBefore);
+        certGen.setNotAfter(notAfter);
+        certGen.setPublicKey(rootPair.getPublic());
+        certGen.setSignatureAlgorithm(SIGNATURE_ALGORITHM);
+
+        certGen.addExtension(X509Extensions.BasicConstraints, true,
+                new BasicConstraints(0));
+
+        certGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.digitalSignature
+                | KeyUsage.keyEncipherment | KeyUsage.keyCertSign));
+
+        AuthorityKeyIdentifier authIdentifier = SslUtil.createAuthorityKeyIdentifier(
+                rootPair.getPublic(), dnName, serialNumber);
+
+        certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, true, authIdentifier);
+        certGen.addExtension(X509Extensions.SubjectKeyIdentifier, true,
+                new SubjectKeyIdentifierStructure(rootPair.getPublic()));
+
+        certGen.addExtension(X509Extensions.SubjectAlternativeName, false, new GeneralNames(
+                new GeneralName(GeneralName.rfc822Name, EMAIL)));
+
+        X509Certificate cert = certGen.generate(rootPair.getPrivate());
+        return cert;
+    }
+
+
+    /**
+     * Given a public key and an authority certificate and key pair, issue an X509 Certificate
+     * chain signed by the provided authority certificate.
+     *
+     * @param name Common name used in the issued certificate.
+     * @param publicKey Public key to use in issued certificate.
+     * @param rootCert Root certificate used to issue the new certificate.
+     * @param rootPair Root key pair used to issue the new certificate.
+     * @return Array containing the issued certificate and the provided root certificate.
+     * @throws GeneralSecurityException
+     */
+    public static X509Certificate[] issueX509V3Certificate(String name, PublicKey publicKey,
+            X509Certificate rootCert, KeyPair rootPair) throws GeneralSecurityException {
+        Calendar calendar = Calendar.getInstance();
+        calendar.add(Calendar.DAY_OF_YEAR, NOT_BEFORE_NUMBER_OF_DAYS);
+        Date notBefore  = new Date(calendar.getTimeInMillis());
+        calendar.add(Calendar.DAY_OF_YEAR, NOT_AFTER_NUMBER_OF_DAYS);
+        Date notAfter = new Date(calendar.getTimeInMillis());
+
+        BigInteger serialNumber = BigInteger.valueOf(Math.abs(System.currentTimeMillis()));
+
+        return issueX509V3Certificate(name, publicKey, rootCert, rootPair, notBefore, notAfter, serialNumber);
+    }
+
+    @SuppressWarnings("deprecation")
+    static X509Certificate[] issueX509V3Certificate(String name, PublicKey publicKey,
+            X509Certificate rootCert, KeyPair rootPair, Date notBefore, Date notAfter,
+            BigInteger serialNumber) throws GeneralSecurityException {
+
+        X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+
+        X509Name dnName = new X509Name(name);
+
+        certGen.setSerialNumber(serialNumber);
+        certGen.setIssuerDN(rootCert.getSubjectX500Principal());
+        certGen.setNotBefore(notBefore);
+        certGen.setNotAfter(notAfter);
+        certGen.setSubjectDN(dnName);
+        certGen.setPublicKey(publicKey);
+        certGen.setSignatureAlgorithm(SIGNATURE_ALGORITHM);
+
+        // Use Root Certificate as the authority
+        certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false,
+                new AuthorityKeyIdentifierStructure(rootCert));
+        // Use provided public key for the subject
+        certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false,
+                new SubjectKeyIdentifierStructure(publicKey));
+        // This is not a CA certificate, do not allow
+        certGen.addExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(false));
+        // This can be used for signature and encryption
+        certGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.digitalSignature
+                | KeyUsage.keyEncipherment));
+        // This is used for server authentication
+        certGen.addExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage(
+                KeyPurposeId.id_kp_serverAuth));
+
+        X509Certificate issuedCert = certGen.generate(rootPair.getPrivate());
+
+        return new X509Certificate[] { issuedCert, rootCert };
+    }
+}
diff --git a/java/src/com/google/polo/ssl/SslUtil.java b/java/src/com/google/polo/ssl/SslUtil.java
index cf0b3da..3d092b3 100644
--- a/java/src/com/google/polo/ssl/SslUtil.java
+++ b/java/src/com/google/polo/ssl/SslUtil.java
@@ -93,11 +93,10 @@
    * @throws GeneralSecurityException  on error generating the certificate
    */
   @SuppressWarnings("deprecation")
+  @Deprecated
   public static X509Certificate generateX509V1Certificate(KeyPair pair,
       String name)
         throws GeneralSecurityException {
-    java.security.Security.addProvider(
-        new org.bouncycastle.jce.provider.BouncyCastleProvider());
 
     Calendar calendar = Calendar.getInstance();
     calendar.set(2009, 0, 1);
@@ -118,9 +117,7 @@
     certGen.setPublicKey(pair.getPublic());
     certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
     
-    // This method is deprecated, but Android Eclair does not provide the 
-    // generate() methods.
-    X509Certificate cert = certGen.generateX509Certificate(pair.getPrivate(), "BC");
+    X509Certificate cert = certGen.generate(pair.getPrivate());
     return cert;
   }
   
@@ -139,8 +136,6 @@
   public static X509Certificate generateX509V3Certificate(KeyPair pair,
       String name, Date notBefore, Date notAfter, BigInteger serialNumber)
         throws GeneralSecurityException {
-    java.security.Security.addProvider(
-        new org.bouncycastle.jce.provider.BouncyCastleProvider());
 
     X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
     X509Name dnName = new X509Name(name);
@@ -186,11 +181,9 @@
         new SubjectKeyIdentifierStructure(pair.getPublic()));
 
     certGen.addExtension(X509Extensions.SubjectAlternativeName, false, new GeneralNames(
-        new GeneralName(GeneralName.rfc822Name, "googletv@test.test")));
+        new GeneralName(GeneralName.rfc822Name, "android-tv-remote-support@google.com")));
 
-    // This method is deprecated, but Android Eclair does not provide the 
-    // generate() methods.
-    X509Certificate cert = certGen.generateX509Certificate(pair.getPrivate(), "BC");
+    X509Certificate cert = certGen.generate(pair.getPrivate());
     return cert;
   }
   
@@ -214,7 +207,7 @@
    * @param serialNumber  the serial number
    * @return  a new {@link AuthorityKeyIdentifier}
    */
-  private static AuthorityKeyIdentifier createAuthorityKeyIdentifier(
+  static AuthorityKeyIdentifier createAuthorityKeyIdentifier(
       PublicKey publicKey, X509Name name, BigInteger serialNumber) {
     GeneralName genName = new GeneralName(name);
     SubjectPublicKeyInfo info;