create a self signed cert and add public key to foaf. including tests.
--- 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