Last active
June 30, 2016 13:37
-
-
Save rbobillot/81a41c3184ab94c162de4f52fd467c8a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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