Jena does not support D-entailment on xsd:hexBinary so because of the danger of there possibly being a white space in front or at the end of the number we cannot limit ourselves to the ASK query. https://issues.apache.org/jira/browse/JENA-170 webid
authorHenry Story <henry.story@bblfish.net>
Mon, 19 Dec 2011 23:41:13 +0100
branchwebid
changeset 154 697b8fe7cb0d
parent 153 37dd439c9383
child 155 021d9a149656
Jena does not support D-entailment on xsd:hexBinary so because of the danger of there possibly being a white space in front or at the end of the number we cannot limit ourselves to the ASK query. https://issues.apache.org/jira/browse/JENA-170
src/main/scala/auth/WebIdClaim.scala
src/test/scala/auth/secure_specs.scala
--- a/src/main/scala/auth/WebIdClaim.scala	Mon Dec 19 18:02:50 2011 +0100
+++ b/src/main/scala/auth/WebIdClaim.scala	Mon Dec 19 23:41:13 2011 +0100
@@ -24,13 +24,14 @@
 package org.w3.readwriteweb.auth
 
 import java.security.interfaces.RSAPublicKey
-import com.hp.hpl.jena.query.{QueryExecutionFactory, QueryExecution, QuerySolutionMap, QueryFactory}
-import com.hp.hpl.jena.datatypes.xsd.XSDDatatype
 import scalaz.{Scalaz, Validation}
 import Scalaz._
 import java.security.PublicKey
 import com.hp.hpl.jena.rdf.model.Model
 import java.net.URL
+import com.hp.hpl.jena.query._
+import java.math.BigInteger
+import com.hp.hpl.jena.datatypes.xsd.XSDDatatype
 
 
 /**
@@ -42,10 +43,12 @@
  */
 object WebIDClaim {
   final val cert: String = "http://www.w3.org/ns/auth/cert#"
-
-  val askQuery = QueryFactory.create("""
+  val numericDataTypes = List(XSDDatatype.XSDinteger, XSDDatatype.XSDint, XSDDatatype.XSDpositiveInteger, XSDDatatype.XSDdecimal)
+  //we cannot do the simpler ask query as Jena does not do Sparql d-entailment on xsd:hexBinary
+  val query = QueryFactory.create("""
       PREFIX : <http://www.w3.org/ns/auth/cert#>
-      ASK {
+      SELECT ?m ?e
+      WHERE {
           ?webid :key [ :modulus ?m ;
                         :exponent ?e ].
       }""")
@@ -59,18 +62,33 @@
  */
 class WebIDClaim(val san: String, val key: PublicKey) {
 
-  import WebIDClaim.hex
+  import WebIDClaim._
   import XSDDatatype._
 
   private def rsaTest(webid: WebID, rsakey: RSAPublicKey): (Model) => Validation[WebIDVerificationFailure, WebID] = {
     model =>
       val initialBinding = new QuerySolutionMap();
       initialBinding.add("webid", model.createResource(webid.url.toString))
-      initialBinding.add("m", model.createTypedLiteral(hex(rsakey.getModulus.toByteArray), XSDhexBinary))
-      initialBinding.add("e", model.createTypedLiteral(rsakey.getPublicExponent.toString, XSDinteger))
-      val qe: QueryExecution = QueryExecutionFactory.create(WebIDClaim.askQuery, model, initialBinding)
+      //      initialBinding.add("m", model.createTypedLiteral(hex(rsakey.getModulus.toByteArray), XSDhexBinary))
+      //      initialBinding.add("e", model.createTypedLiteral(rsakey.getPublicExponent.toString, XSDinteger))
+      val qe: QueryExecution = QueryExecutionFactory.create(WebIDClaim.query, model, initialBinding)
       try {
-        if (qe.execAsk()) webid.success
+        def matches: Boolean = {
+          import scala.collection.JavaConversions._
+          val resultset = qe.execSelect().toSet
+          resultset.exists {
+            sol: QuerySolution => try {
+              val mod = sol.getLiteral("m")
+              if (mod.getDatatype == XSDDatatype.XSDhexBinary && new BigInteger(mod.getLexicalForm.trim(), 16) == rsakey.getModulus) {
+                val exp = sol.getLiteral("e")
+                numericDataTypes.contains(exp.getDatatype) && new BigInteger(exp.getLexicalForm) == rsakey.getPublicExponent
+              } else false
+            } catch {
+              case _ => false
+            }
+          }
+        }
+        if (matches) webid.success
         else new WebIDVerificationFailure("could not verify public key", None, this).fail
       } finally {
         qe.close()
--- a/src/test/scala/auth/secure_specs.scala	Mon Dec 19 18:02:50 2011 +0100
+++ b/src/test/scala/auth/secure_specs.scala	Mon Dec 19 23:41:13 2011 +0100
@@ -93,7 +93,7 @@
 
 
 
-  val webCache = new WebCache()
+  val webCache = WebCache
   val serverSslContext = javax.net.ssl.SSLContext.getInstance("TLS");
 
 
@@ -110,7 +110,7 @@
   val rww = new cycle.Plan  with cycle.ThreadPool with ServerErrorResponse with ReadWriteWeb[ReceivedMessage,HttpResponse] {
     val rm = resourceManager
     def manif = manifest[ReceivedMessage]
-    override val authz = new RDFAuthZ[ReceivedMessage,HttpResponse](webCache,resourceManager)
+    override val authz = new RDFAuthZ[ReceivedMessage,HttpResponse](resourceManager)
   }
 
   def setup = { _.plan(rww) }