Skip to content

Instantly share code, notes, and snippets.

@rbobillot
Last active June 30, 2016 13:37
Show Gist options
  • Save rbobillot/81a41c3184ab94c162de4f52fd467c8a to your computer and use it in GitHub Desktop.
Save rbobillot/81a41c3184ab94c162de4f52fd467c8a to your computer and use it in GitHub Desktop.
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.InputStream
import java.io.BufferedInputStream
import java.io.BufferedOutputStream
trait GlobalInfos {
val plainName = "plainImage"
val cryptName = "cryptImage"
val flickrLink = "https://www.flickr.com/explore"
val cryptShift = 1 << 4
}
case class Pic(file:InputStream, name:String)
object ImageHandler {
def getBuffSize(buffer:BufferedInputStream) = buffer.available
def checkMessageSize(message:String, in:BufferedInputStream, shift:Int) =
if (message.size >= (getBuffSize(in) / shift) - 320) {
println("\u001b[91mMessage's too big, please shorten it\u001b[0m")
in.close ; sys exit -1
}
def read(inputStream:InputStream)(implicit shift:Int = 0) = {
var c = 0
var i = 0
var isMessageEnd = false
val inputFile = new BufferedInputStream(inputStream)
var accumulator = List[Char]()
while (-1 != c) {
c = inputFile.read
if (i >= 320 && 0 == i % shift && !isMessageEnd) {
if (0 == c) isMessageEnd = true
accumulator ::= c.toChar
}
i += 1
}
inputFile.close
accumulator.mkString
}
def write(inputStream:InputStream, ext:String, output:String)(implicit message:String = "", shift:Int = 0) = {
var c = 0
var i = 0
var msgIndex = 0
val inputFile = new BufferedInputStream(inputStream)
if (0 < shift) checkMessageSize(message, inputFile, shift)
val outputFile = new BufferedOutputStream(new FileOutputStream(s"$output.$ext"))
while (-1 != c) {
c = inputFile.read
if (i >= 320 && 0 < shift && 0 == i % shift && msgIndex <= message.size) {
outputFile write (if (msgIndex == message.size) 0 else message reverse msgIndex)
msgIndex += 1
} else if (-1 != c) outputFile write c
i += 1
}
inputFile.close
outputFile.close
}
}
object GetPicture extends GlobalInfos {
import java.net.URL
import java.io.File
import scala.io.Source.fromURL
import scala.util.Random.nextInt
private def getRandElementFromArray[T](arr:Array[T]) = arr( nextInt(arr.size) )
private def checkImageInfosFromDiv(div:String) = """width: .*px;|height: .*px;|url\(.*\)""".r
.findAllIn("""style="transform.*\)"""".r
.findAllIn(div).mkString).mkString.split(";( ?)")
.map(x => """width: |height: |px|\)""".r.replaceAllIn(x, ""))
private def getRandomLink = {
val lines = fromURL(flickrLink).getLines.filter(_ contains "background-image").toArray
val rawLines = lines map checkImageInfosFromDiv
val jpgLines = rawLines.filter(x => (x(0).toInt * x(1).toInt) > 128000).map("http:" + _.last.drop(4))
getRandElementFromArray( jpgLines )
}
private def getRandomPic = {
val link = getRandomLink
val img = new URL(link).openStream
Pic(img, cryptName)
}
def getPic = {
val filesInCurDir = new File(".").listFiles
val srcFiles = filesInCurDir.filter(_.getName == (plainName+".jpg"))
if (srcFiles.isEmpty) {
println("\u001b[33mGetting random picture for ciphering\u001b[0m")
val randomPic = getRandomPic
ImageHandler.write(randomPic.file, "jpg", plainName)
println(s"\u001b[93mRandom pic saved in current directory\u001b[0m ( $plainName.jpg )")
randomPic
} else {
println("\u001b[33mPlain picture found in current directory\u001b[0m")
val fileStream = new FileInputStream(srcFiles.head)
println(s"$plainName.jpg \u001b[93mwill be used for ciphering\u001b[0m")
Pic(fileStream, cryptName)
}
}
}
object Main extends GlobalInfos {
def usage = {
println(
"""|usage: scala stega.jar <OPTIONS> <ARGUMENTS>
|
| -c <MESSAGE_TO_HIDE> : Takes a random picture from Flickr.com, and hides a message into a clone
| -d <IMG_CIPHERED> : Analyses a ciphered picture, to get the original message""".stripMargin
)
sys exit -1
}
def encryptPicture(message:String): Unit = {
val random = GetPicture.getPic
println("\u001b[95mHiding your message into a picture\u001b[0m")
ImageHandler.write(new FileInputStream(plainName+".jpg"), "jpg", cryptName)(message, cryptShift)
println(s"\u001b[92mMessage hidden into\u001b[0m $cryptName.jpg")
}
def decryptPicture(image:String) =
println( ImageHandler.read(new FileInputStream(image))(cryptShift) )
def main(av:Array[String]) = av.size match {
case 2 => av.toList match {
case "-c" :: mesg :: Nil => encryptPicture(mesg)
case "-d" :: file :: Nil => decryptPicture(file)
case _ => usage
}
case _ => usage
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment