1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
package com.github.jodersky.skeybase
package verification
import scala.language.implicitConversions
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import scala.util.Failure
import scala.util.Success
import scala.util.Try
import com.github.jodersky.skeybase.Proof
import com.github.jodersky.skeybase.PublicKey
import akka.actor.ActorSystem
import spray.http.HttpHeaders.Location
import spray.http.HttpRequest
import spray.http.HttpResponse
import spray.http.Uri
import spray.json.DefaultJsonProtocol
import spray.json.JsonParser
import spray.json.ParserInput.apply
trait Verifier {
def verify(fingerprint: String, proof: Proof)(implicit sys: ActorSystem): Future[Proof]
}
object Verifier {
object JsonProtocol extends DefaultJsonProtocol {
implicit val serviceFormat = jsonFormat2(Service.apply)
implicit val keyFormat = jsonFormat1(PublicKey.apply)
implicit val statementBodyFormat = jsonFormat2(StatementBody.apply)
implicit val statementFormat = jsonFormat1(Statement.apply)
}
import JsonProtocol._
implicit def tryToFuture[A](t: Try[A]): Future[A] = t match {
case Success(a) => Future.successful(a)
case Failure(e) => Future.failed(e)
}
def withRedirects(
sendReceive: HttpRequest => Future[HttpResponse],
maxRedirects: Int = 5)(implicit ec: ExecutionContext): HttpRequest => Future[(Uri, HttpResponse)] = { request =>
def dispatch(request: HttpRequest, redirectsLeft: Int): Future[(Uri, HttpResponse)] = if (redirectsLeft <= 0) {
Future.failed(new RuntimeException("Too many redirects."))
} else {
sendReceive(request).flatMap { response =>
if (response.status.value.startsWith("3")) {
response.header[Location].map { location =>
dispatch(request.copy(uri = location.uri), redirectsLeft - 1)
} getOrElse {
Future.failed(new RuntimeException("Missing location header in redirect response."))
}
} else {
Future.successful(request.uri, response)
}
}
}
dispatch(request, maxRedirects)
}
def finalHost(host: String) = (uri: Uri, response: HttpResponse) => {
if (uri.authority.host.address != host)
throw new VerificationException("Final host is not " + host)
else
response
}
def extractSignedStatement(content: String): Try[String] = Try {
val regex = """(-----BEGIN PGP MESSAGE-----(.|\n)*-----END PGP MESSAGE-----?)""".r
regex.findFirstIn(content) getOrElse {
throw new VerificationException("No OpenPGP message found.")
}
}
def verifyStatement(statement: String, service: String, username: String): Try[String] = Try {
val stmt = JsonParser(statement).convertTo[Statement]
if (stmt.body.service.name != service) throw new VerificationException(
"The service specified in the signed statement (" + stmt.body.service.name + ") is not " +
"the same as the service under which the statement was found (" + service + ")")
else if (stmt.body.service.username != username) throw new VerificationException(
"The username specified in the signed statement (" + stmt.body.service.username + ") is not " +
"the same as the username under which the statement was found (" + username + ")")
else statement
}
/*
* if (!(uri.path.tail startsWith (Path(proof.nametag)))) {
* throw new VerificationException("Final github account does not match the one provided in the proof." + uri.path.head)
* }
def extractHtmlId(id: String, html: String): Option[String] = {
val cleaner = new HtmlCleaner
val root = cleaner.clean(html)
root.getElementsByName("div", true).find(_.getAttributeByName("id") == id).map { div =>
StringEscapeUtils.unescapeHtml4(div.getText.toString())
}
}*/
}
|