Initial commit for the framework

The ChallengeProvider trait provides the methods to be implemented by the challenge providers.

The framework gets a challenge from a challenge provider, inserts the details of the challenge into the database, and gives the challenge to the user. It then gets the answer from the user, and sends it to the challenge provider for verification.

This commit includes the implementation only for FilterChallenge provider.
This commit is contained in:
sanjana 2018-06-06 12:18:40 +05:30
parent 758eb4d9b9
commit f73f2a762f
7 changed files with 94 additions and 149 deletions

View File

@ -16,3 +16,5 @@ lazy val root = (project in file(".")).
libraryDependencies += "com.sksamuel.scrimage" %% "scrimage-filters" % "2.1.8"
)
fork in run := true

BIN
lib/h2-1.4.197.jar Executable file

Binary file not shown.

View File

@ -1,24 +0,0 @@
import com.sksamuel.scrimage._
import com.sksamuel.scrimage.filter.GaussianBlurFilter
import java.io._
class BlurCaptcha extends CaptchaProvider {
val tokenAnswer = scala.collection.mutable.Map[String, String]()
val imageFiles = new File("known").listFiles.toList
def getChallenge(): (Challenge) = {
val r = scala.util.Random.nextInt(imageFiles.length)
val chosenImage = imageFiles(r)
var image = Image.fromStream(new FileInputStream(chosenImage))
val blur = new GaussianBlurFilter(5)
blur.apply(image)
val s = scala.util.Random
val token = s.nextInt(10000).toString
val challenge = new Challenge(token, image)
val answer = "about"
tokenAnswer += token -> answer
challenge
}
def checkAnswer(token: String, input: String): Boolean = {
tokenAnswer(token) == input
}
}

View File

@ -1,68 +0,0 @@
import java.io.File
import javax.imageio.ImageIO
import scala.collection.mutable.Map
import java.nio.file.{Files,Path,StandardCopyOption}
import java.awt.image.BufferedImage
import java.awt.{Graphics2D,Color}
class LabelCaptcha extends CaptchaProvider {
var knownFiles = new File("known").list.toList
var unknownFiles = new File("unknown").list.toList
val tokenImagePair = Map[String, ImagePair]()
val unknownAnswers = Map[String, Map[String, Int]]()
val total = Map[String, Int]()
for(file <- unknownFiles) {
unknownAnswers += file -> Map[String, Int]()
total += file -> 0
}
def getChallenge(): Challenge = synchronized {
val r = scala.util.Random.nextInt(knownFiles.length)
val s = scala.util.Random.nextInt(unknownFiles.length)
val knownImageFile = knownFiles(r)
val unknownImageFile = unknownFiles(s)
val ip = new ImagePair(knownImageFile, unknownImageFile)
val token = scala.util.Random.nextInt(10000).toString
tokenImagePair += token -> ip
var knownImage = ImageIO.read(new File("known/"+knownImageFile))
var unknownImage = ImageIO.read(new File("unknown/"+unknownImageFile))
val width = knownImage.getWidth()+unknownImage.getWidth()
val height = List(knownImage.getHeight(), unknownImage.getHeight()).max
val imageType = knownImage.getType()
val finalImage = new BufferedImage(width, height, imageType)
val g = finalImage.createGraphics()
g.setColor(Color.WHITE)
g.fillRect(0, 0, finalImage.getWidth(), finalImage.getHeight())
g.drawImage(knownImage, null, 0, 0)
g.drawImage(unknownImage, null, knownImage.getWidth(), 0)
g.dispose()
val challenge = new Challenge(token, finalImage)
challenge
}
def checkAnswer(token: String, input: String): Boolean = synchronized {
val expectedAnswer = tokenImagePair(token).known.split('.')(0)
val userAnswer = input.split(' ')
if(userAnswer(0)==expectedAnswer) {
val unknownFile = tokenImagePair(token).unknown
if((unknownAnswers(unknownFile)).contains(userAnswer(1))) {
unknownAnswers(unknownFile)(userAnswer(1)) += 1
total(unknownFile) += 1
} else {
unknownAnswers(unknownFile)+=(userAnswer(1)) -> 1
total(unknownFile) += 1
}
if(total(unknownFile)>=3) {
if((unknownAnswers(unknownFile)(userAnswer(1))/total(unknownFile))>=0.9) {
unknownAnswers -= unknownFile
Files.move(new File("unknown/"+unknownFile).toPath, new File("known/"+userAnswer(1)+".png").toPath, StandardCopyOption.REPLACE_EXISTING)
knownFiles = new File("known").list.toList
unknownFiles = new File("unknown").list.toList
}
}
true
} else {
false
}
}
}
class ImagePair(val known: String, val unknown: String)

View File

@ -1,43 +0,0 @@
import com.sksamuel.scrimage._
import java.io._
class CaptchaLibrary {
val captchas = List(new BlurCaptcha, new LabelCaptcha, new FilterCaptcha)
var tokenCaptcha = scala.collection.mutable.Map[String, CaptchaProvider]()
def init = {}
def shutdown = {}
def getChallenge(): Challenge = {
//choose a captcha provider randomly
val r = scala.util.Random.nextInt(2)
val captchaInstance = captchas(r)
val challenge = captchaInstance.getChallenge()
tokenCaptcha += challenge.token -> captchaInstance
challenge
}
def checkAnswer(token: String, input: String): Boolean = {
val result = tokenCaptcha(token).checkAnswer(token, input)
result
}
}
trait CaptchaProvider {
def getChallenge(): (Challenge)
def checkAnswer(token: String, input: String): Boolean
}
class Challenge(val token: String, val image: Image)
class Answer(val token: String, val input: String)
object LibreCaptcha {
def main(args: Array[String]) {
val captcha = new CaptchaLibrary
val challenge = captcha.getChallenge()
println(s"Token: ${challenge.token}")
challenge.image.output(new File("Captcha.png"))
println("Enter your answer: ")
val input = scala.io.StdIn.readLine()
val result = captcha.checkAnswer(challenge.token, input)
println(s"Result: $result")
}
}

View File

@ -1,36 +1,34 @@
package lc
import com.sksamuel.scrimage._
import com.sksamuel.scrimage.filter._
import java.awt.image.BufferedImage
import java.awt.{Graphics2D,Color,Font}
import java.awt.Font
import java.awt.Color
class FilterCaptcha extends CaptchaProvider {
val tokenAnswer = scala.collection.mutable.Map[String, String]()
def getChallenge(): Challenge = {
class FilterChallenge extends ChallengeProvider {
val id = "filter"
def returnChallenge(): (Image, String) = {
val filterTypes = List(new FilterType1, new FilterType2)
val r = new scala.util.Random
val alphabet = "abcdefghijklmnopqrstuvwxyz"
val n = 8
val answer = Stream.continually(r.nextInt(alphabet.size)).map(alphabet).take(n).mkString
val token = scala.util.Random.nextInt(10000).toString
synchronized {
tokenAnswer += token -> answer
}
val secret = Stream.continually(r.nextInt(alphabet.size)).map(alphabet).take(n).mkString
val canvas = new BufferedImage(225, 50, BufferedImage.TYPE_INT_RGB)
val g = canvas.createGraphics()
g.setColor(Color.WHITE)
g.fillRect(0, 0, canvas.getWidth, canvas.getHeight)
g.setColor(Color.BLACK)
g.setFont(new Font("Serif", Font.PLAIN, 30))
g.drawString(answer, 5, 30)
g.drawString(secret, 5, 30)
g.dispose()
var image = new Image(canvas, ImageMetadata.empty)
val s = scala.util.Random.nextInt(2)
image = filterTypes(s).applyFilter(image)
val challenge = new Challenge(token, image)
challenge
(image, secret)
}
def checkAnswer(token: String, input: String): Boolean = {
tokenAnswer(token) == input
def checkAnswer(secret: String, answer: String): Boolean = {
secret == answer
}
}
@ -61,3 +59,4 @@ class FilterType2 extends FilterType {
image
}
}

View File

@ -0,0 +1,79 @@
package lc
import com.sksamuel.scrimage._
import java.sql._
import java.io._
trait ChallengeProvider {
val id: String
def returnChallenge(): (Image, String)
def checkAnswer(secret: String, answer: String): Boolean
//TODO: def configure(): Unit
}
class Captcha {
val con: Connection = DriverManager.getConnection("jdbc:h2:./captcha", "sa", "")
val stmt: Statement = con.createStatement();
stmt.execute("CREATE TABLE IF NOT EXISTS challenge(token varchar, id varchar, secret varchar, image blob)");
def getCaptcha(): Boolean = {
val provider = new FilterChallenge
val (token, image) = this.getChallenge(provider)
val stmt: Statement = con.createStatement();
image.output(new File("Captcha.png"))
println(s"Token: ${token}")
println("Enter your answer: ")
val answer = scala.io.StdIn.readLine()
this.getAnswer(token, answer, provider)
}
def getChallenge(provider: ChallengeProvider): (String, Image) = {
val (image, secret) = provider.returnChallenge()
val token = scala.util.Random.nextInt(10000).toString
var pstmt: PreparedStatement = null
pstmt = con.prepareStatement("INSERT INTO challenge(token, id, secret) VALUES (?, ?, ?)")
pstmt.setString(1, token)
pstmt.setString(2, provider.id)
pstmt.setString(3, secret)
//TODO: insert image into database
pstmt.executeUpdate()
(token, image)
}
def getAnswer(token: String, answer: String, provider: ChallengeProvider): Boolean = {
val stmt: Statement = con.createStatement();
val rs: ResultSet = stmt.executeQuery("SELECT secret FROM challenge WHERE token = "+token);
rs.next()
val secret = rs.getString("secret")
provider.checkAnswer(secret, answer)
}
def display(): Unit = {
val stmt: Statement = con.createStatement();
val rs: ResultSet = stmt.executeQuery("SELECT * FROM challenge");
println("token\t\tid\t\tsecret\t\timage");
while(rs.next()) {
val token = rs.getString("token");
val id = rs.getString("id");
val secret = rs.getString("secret");
val image = rs.getString("image");
println(s"${token}\t\t${id}\t\t${secret}\t\t${image}")
}
}
def closeConnection(): Unit = {
con.close()
}
}
object LCFramework{
def main(args: scala.Array[String]) {
val captcha = new Captcha
val result = captcha.getCaptcha()
println(result)
captcha.display()
captcha.closeConnection()
}
}