create a self signed cert and add public key to foaf. including tests. webid
authorHenry Story <henry.story@bblfish.net>
Wed, 26 Oct 2011 16:12:18 +0200
branchwebid
changeset 101 0e91da4bc405
parent 100 09d4f2d2e8f3
child 102 9ca474c333e8
create a self signed cert and add public key to foaf. including tests.
src/main/scala/auth/X509Cert.scala
src/test/scala/auth/CreateWebIDSpec.scala
--- a/src/main/scala/auth/X509Cert.scala	Tue Oct 25 16:03:57 2011 +0200
+++ b/src/main/scala/auth/X509Cert.scala	Wed Oct 26 16:12:18 2011 +0200
@@ -28,6 +28,55 @@
 import unfiltered.netty.ReceivedMessage
 import java.security.cert.{X509Certificate}
 import java.security.cert.Certificate
+import java.util.Date
+import java.math.BigInteger
+import java.security.{SecureRandom, KeyPair}
+import sun.security.x509._
+
+object X509Cert {
+  val WebID_DN="""O=FOAF+SSL, OU=The Community of Self Signers, CN=Not a Certification Authority"""
+
+  /**
+   * Adapted from http://bfo.com/blog/2011/03/08/odds_and_ends_creating_a_new_x_509_certificate.html
+   * The libraries used here are sun gpled code. This is much lighter to use than bouncycastle. All VMs that already
+   * have these classes don't need to download the code. It should be easy in scala to create a build that can decide
+   * if these need to be added to the classpath. I think the code just looks better than bouncycastle too.
+   *
+   * Create a self-signed X.509 Certificate
+   * @param issuerDN the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB"
+   * @param pair the KeyPair
+   * @param days how many days from now the Certificate is valid for
+   * @param algorithm the signing algorithm, eg "SHA1withRSA"
+   */
+    def generate_self_signed(issuerDN: String,
+                 pair: KeyPair,
+                 days: Int, 
+                 algorithm: String="SHA1withRSA"): X509Certificate = {
+      var info = new X509CertInfo
+      val from = new Date
+      val to = new Date(from.getTime + days*24*60*60*1000) 
+      val interval = new CertificateValidity(from, to)
+      val sn = new BigInteger(64, new SecureRandom)
+      val owner = new X500Name(issuerDN)
+      info.set(X509CertInfo.VALIDITY, interval)
+      info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn))
+      info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner))
+      info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner))
+      info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic))
+      info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3))
+      val algo: AlgorithmId = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid)
+      info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo))
+      var cert: X509CertImpl = new X509CertImpl(info)
+      cert.sign(pair.getPrivate, algorithm)
+      val sigAlgo = cert.get(X509CertImpl.SIG_ALG).asInstanceOf[AlgorithmId]
+      info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, sigAlgo)
+      cert = new X509CertImpl(info)
+      cert.sign(pair.getPrivate, algorithm)
+      return cert
+    }
+
+
+}
 
 
 object Certs {
--- a/src/test/scala/auth/CreateWebIDSpec.scala	Tue Oct 25 16:03:57 2011 +0200
+++ b/src/test/scala/auth/CreateWebIDSpec.scala	Wed Oct 26 16:12:18 2011 +0200
@@ -26,13 +26,14 @@
 import org.w3.readwriteweb.utiltest._
 
 import dispatch._
-import org.w3.readwriteweb.TURTLE
-import java.security.KeyStore
-import java.io.{FileInputStream, File}
+import java.io.File
 import org.apache.http.conn.scheme.Scheme
-import javax.net.ssl.{X509TrustManager, TrustManager, TrustManagerFactory}
-import java.security.cert.X509Certificate
+import javax.net.ssl.{X509TrustManager, TrustManager}
 import java.lang.String
+import java.security.cert.{CertificateFactory, X509Certificate}
+import java.security._
+import interfaces.RSAPublicKey
+import org.w3.readwriteweb.{RDFXML, TURTLE}
 
 /**
  * @author hjs
@@ -49,7 +50,6 @@
   lazy val lambdaDir = new File(directory,"Lambda")
 
 {
-  val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
   val  sslContext = javax.net.ssl.SSLContext.getInstance("TLS");
   sslContext.init(null, Array[TrustManager](new X509TrustManager {
     def checkClientTrusted(chain: Array[X509Certificate], authType: String) {}
@@ -72,7 +72,24 @@
        :jl a foaf:Person;
            foaf:name "Joe Lambda"@en .
   """
+  
+  val updatePk = """
+       PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+       PREFIX cert: <http://www.w3.org/ns/auth/cert#>
+       PREFIX rsa: <http://www.w3.org/ns/auth/rsa#>
+       PREFIX : <#>
+       INSERT DATA {
+         :j1 foaf:key [ rsa:modulus "%s"^^cert:hex;
+                        rsa:public_exponent "%s"^^cert:int ] .
+       }
+  """
 
+  val rsagen = KeyPairGenerator.getInstance("RSA")
+  rsagen.initialize(512)
+  val rsaKP = rsagen.generateKeyPair()
+  val certFct = CertificateFactory.getInstance("X.509")
+  val testCert = X509Cert.generate_self_signed("CN=RoboTester, OU=DIG, O=W3C",rsaKP,1)
+  val testCertPk: RSAPublicKey = testCert.getPublicKey.asInstanceOf[RSAPublicKey]
   
   "PUTing nothing on /people/" should {
        "return a 201" in {
@@ -105,4 +122,25 @@
         joeProfileOnDisk must be file
      }
    }
+
+   "POSTing public key into the /people/Lambda/Joe profile" should {
+     "return a 200" in {
+       val updateQ = updatePk.format(
+                     testCertPk.getModulus.toString(16),
+                     testCertPk.getPublicExponent()
+       )
+       System.out.println(updateQ)
+       val httpCode = Http(
+         webidProfile.secure.postSPARQL(updateQ) get_statusCode )
+        httpCode must_== 200
+     }
+     "create 3 more relations" in {
+       val model = Http(webidProfile.secure as_model(baseURI(webidProfile.secure), RDFXML))
+       model.size() must_== 7
+         
+     }
+   }
+
+
+
 }
\ No newline at end of file