Last active
September 13, 2017 16:29
-
-
Save rbobillot/47b30d40a489615ff947b16d1c17216d 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
object HideText { | |
type Homoglyphs = Map[Char, Array[Char]] | |
val homoglyphsDict: Homoglyphs = Map( | |
' ' -> Array("2000","2001","2002","2003","2004","2005","2006","2007","2008","2009","200A","2028","2029","202F","205F"), | |
'!' -> Array("FF01"), | |
'"' -> Array("FF02"), | |
'$' -> Array("FF04"), | |
'%' -> Array("FF05"), | |
'&' -> Array("FF06"), | |
'\'' -> Array("FF07"), | |
'(' -> Array("FF08"), | |
')' -> Array("FF09"), | |
'*' -> Array("FF0A"), | |
'+' -> Array("FF0B"), | |
',' -> Array("FF0C"), | |
'-' -> Array("FF0D"), | |
'.' -> Array("FF0E"), | |
'/' -> Array("FF0F"), | |
'0' -> Array("FF10"), | |
'1' -> Array("FF11"), | |
'2' -> Array("FF12"), | |
'3' -> Array("FF13"), | |
'4' -> Array("FF14"), | |
'5' -> Array("FF15"), | |
'6' -> Array("FF16"), | |
'7' -> Array("FF17"), | |
'8' -> Array("FF18"), | |
'9' -> Array("FF19"), | |
':' -> Array("FF1A"), | |
';' -> Array("FF1B"), | |
'<' -> Array("FF1C"), | |
'=' -> Array("FF1D"), | |
'>' -> Array("FF1E"), | |
'?' -> Array("FF1F"), | |
'@' -> Array("FF20"), | |
'A' -> Array("FF21","0391","0410"), | |
'B' -> Array("FF22","0392","0412"), | |
'C' -> Array("FF23","03F9","216D"), | |
'D' -> Array("FF24"), | |
'E' -> Array("FF25","0395","0415"), | |
'F' -> Array("FF26"), | |
'G' -> Array("FF27"), | |
'H' -> Array("FF28","0397","041D"), | |
'I' -> Array("FF29","0399","0406"), | |
'J' -> Array("FF2A"), | |
'K' -> Array("FF2B","039A","212A"), | |
'L' -> Array("FF2C"), | |
'M' -> Array("FF2D","039C","041C"), | |
'N' -> Array("FF2E"), | |
'O' -> Array("FF2F","039F","041E"), | |
'P' -> Array("FF30","03A1","0420"), | |
'Q' -> Array("FF31"), | |
'R' -> Array("FF32"), | |
'S' -> Array("FF33"), | |
'T' -> Array("FF34","03A4","0422"), | |
'U' -> Array("FF35"), | |
'V' -> Array("FF36","0474","2164"), | |
'W' -> Array("FF37"), | |
'X' -> Array("FF38","03A7","2169"), | |
'Y' -> Array("FF39","03A5","04AE"), | |
'Z' -> Array("FF3A"), | |
'[' -> Array("FF3B"), | |
'\\' -> Array("FF3C"), | |
']' -> Array("FF3D"), | |
'^' -> Array("FF3E"), | |
'_' -> Array("FF3F"), | |
'`' -> Array("FF40"), | |
'a' -> Array("FF41"), | |
'b' -> Array("FF42"), | |
'c' -> Array("FF43","03F2","0441"), | |
'd' -> Array("FF44"), | |
'e' -> Array("FF45"), | |
'f' -> Array("FF46"), | |
'g' -> Array("FF47"), | |
'h' -> Array("FF48"), | |
'i' -> Array("FF49","0456","2170"), | |
'j' -> Array("FF4A"), | |
'k' -> Array("FF4B"), | |
'l' -> Array("FF4C"), | |
'm' -> Array("FF4D"), | |
'n' -> Array("FF4E"), | |
'o' -> Array("FF4F","03BF","043E"), | |
'p' -> Array("FF50"), | |
'q' -> Array("FF51"), | |
'r' -> Array("FF52"), | |
's' -> Array("FF53"), | |
't' -> Array("FF54"), | |
'u' -> Array("FF55"), | |
'v' -> Array("FF56","03BD","2174"), | |
'w' -> Array("FF57"), | |
'x' -> Array("FF58","0445","2179"), | |
'y' -> Array("FF59"), | |
'z' -> Array("FF5A"), | |
'{' -> Array("FF5B"), | |
'|' -> Array("FF5C"), | |
'}' -> Array("FF5D"), | |
'~' -> Array("FF5E") | |
).mapValues(_.map(hex => Integer.parseInt(hex, 16).toChar)) | |
def binToNat(bs: String): BigInt = BigInt(bs, 2) | |
def padWith[T](e: T)(s: String, len: BigInt) = s.reverse.padTo(len.intValue, e).reverse.mkString | |
// ensure secretBits are divisible by alphabetBitsSize | |
def padSecretBits(sb: String, secretAlphabet: String, secretAlphabetBitsSize: Int): String = { | |
if (BigInt(sb) % secretAlphabetBitsSize == 0) sb | |
else sb + padWith(0)("0", secretAlphabetBitsSize - (BigInt(sb) % secretAlphabetBitsSize)) | |
} | |
def secretToBinaryString(secret: String, secretAlphabet: String, secretAlphabetBitsSize: Int): String = { | |
val secretBits = secret.foldLeft(""){ (sb, c) => | |
sb + padWith(0)(secretAlphabet.indexOf(c).toBinaryString, secretAlphabetBitsSize) | |
} | |
padSecretBits(secretBits, secretAlphabet, secretAlphabetBitsSize) | |
} | |
def replaceChar(c: Char, hg: Array[Char], sbits: String) = { | |
val hgBitsSize = (hg.size + 1).toBinaryString.size - 1 | |
val chunkToEncode = sbits take hgBitsSize | |
val nextSecretBits = sbits drop hgBitsSize | |
val n = binToNat(chunkToEncode).intValue | |
nextSecretBits -> hg.lift(n-1).getOrElse(c) | |
} | |
def cipher(msg: String, sbits: String, dict: Homoglyphs, result: String = ""): String = | |
dict.get(msg.head) match { | |
case None => cipher(msg drop 1, sbits, dict, result + msg.head) | |
case Some(homoglyphs) => (sbits, msg.head) match { | |
case ("", ' ') => result | |
case ("", _) => cipher(msg drop 1, sbits, dict, result + msg.head) | |
case (_, c) => val (nbits, nchar) = replaceChar(c, homoglyphs, sbits) | |
cipher(msg drop 1, nbits, dict, result + nchar) | |
} | |
} | |
def encode(msg: String, secret: String)(dict: Homoglyphs): String = { | |
val secretAlphabet: String = " abcdefghijklmnopqrstuvwxyz123456789'0.:/\\%-_?&;" // dict.keys.mkString | |
val secretAlphabetBitsSize: Int = secretAlphabet.size.toBinaryString.size | |
val secretBits: String = secretToBinaryString(secret, secretAlphabet, secretAlphabetBitsSize) | |
cipher(msg, secretBits, dict) | |
} | |
val LOREM = """Lorem ipsum nunc risus lacinia nisi feugiat etiam ad id pellentesque sit suscipit sociosqu nullam, turpis euismod velit id aliquam luctus praesent congue luctus mauris hendrerit posuere suscipit fringilla aptent egestas vivamus scelerisque id nulla inceptos facilisis, ac vehicula bibendum tortor aliquet tristique curabitur elit facilisis, quisque primis urna interdum nisl nulla class litora convallis ut tellus.""" | |
def main(av: Array[String]): Unit = | |
av.toList match { | |
case str :: sec :: Nil => println(encode(str, sec)(homoglyphsDict)) | |
case sec :: Nil => println(encode(LOREM, sec)(homoglyphsDict)) // error 403 | |
case _ => println("usage: scala hide.jar <string> <secret>") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment