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
--- 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) }