Haskell选择性文本混淆

时间:2014-06-02 16:10:11

标签: haskell text functional-programming obfuscation purely-functional

我想混淆文本文件报告,而不会模糊某些关键字,例如报告标题,列标题等。我已经使用newLisp构建了这样的程序。我试图从头开始在Haskell中实现该功能。这是我到目前为止所获得的代码,它为简单混淆的情况编译并成功运行。

module Main where

import Data.Char (isAlpha, isNumber, isUpper, toUpper)
import System.Environment (getArgs)
import System.Random (getStdGen, randomR, StdGen)

helpMessage = [ "Usage: cat filename(s) | obfuscate [-x filename] > filename",
  "",
  "Obfuscates text files. This obliterates the text--there is no recovery. This",
  "is not encryption. It's simple, if slow, obfuscation.",
  "",
  "To include a list of words not to obfuscate, use the -x option. List one word",
  "per line in the file.",
  "" ]

data CLOpts = CLOpts { help           :: Bool
                     , exceptionFileP :: Bool
                     , exceptionFile  :: String }

main = do
  args <- getArgs
  if length args > 0
  then do let opts = parseCL args CLOpts { help=False, exceptionFileP=False, exceptionFile="" }
          if help opts
          then do putStrLn $ unlines helpMessage
          else do if exceptionFileP opts
                  then do exceptions <- readFile $ exceptionFile opts
                          obf complexObfuscation $ lines exceptions
                  else do obf simpleObfuscation []
  else do obf simpleObfuscation []
  where obf f xs = do
          g <- getStdGen
          c <- getContents
          putStrLn $ f xs g c

parseCL :: [String] -> CLOpts -> CLOpts
parseCL []          opts = opts
parseCL ("-x":f:xs) opts = parseCL xs opts { exceptionFileP=True, exceptionFile=f }
parseCL      (_:xs) opts = parseCL xs opts { help=True }

simpleObfuscation xs = obfuscate

complexObfuscation exceptions g c = undefined

obfuscate :: StdGen -> String -> String
obfuscate g = obfuscate' g []
  where
    obfuscate' _ a [] = reverse a
    obfuscate' g a text@(c:cs)
      | isAlpha  c = obf obfuscateAlpha g a text
      | isNumber c = obf obfuscateDigit g a text
      | otherwise  = obf id             g a text
    obf f g a (c:cs) = let (x,g') = f (c,g) in obfuscate' g' (x:a) cs

obfuscateAlpha, obfuscateDigit :: (Char, StdGen) -> (Char, StdGen)
obfuscateAlpha (c,g) = obfuscateChar g range
  where range
          | isUpper c = ('A','Z')
          | otherwise = ('a','z')

obfuscateDigit (c,g) = obfuscateChar g ('0','9')

obfuscateChar :: StdGen -> (Char, Char) -> (Char, StdGen)
obfuscateChar = flip randomR

我无法理解如何混淆除了作为例外传入的单词之外的所有文本。我的newLisp实现依赖于它内置的正则表达式处理。我在Haskell中使用正则表达式并没有太多运气。可能是旧图书馆或其他什么。

我尝试将文本拆分为行和单词,并在J中创建将被称为烦恼的内容。这种方法很快变得笨拙。我尝试使用解析器,但我认为它也会变得非常毛茸茸。

是否有人建议采用简单,直接的方法来识别文本中的异常单词以及如何不将这些单词发送到混淆函数?哈斯克尔是一种如此出色的语言,当然我在我的鼻子底下遗漏了一些东西。

我试过谷歌,但似乎我希望提供一个不混淆的单词的例外列表是新颖的。否则,混淆非常简单。

更新

按照我标记为答案的想法,我创建了自己的words函数:

words' :: String -> [String]
words' text = f text [] []
  where f [] wa ta = reverse $ wa:ta
        f (c:cs) wa ta =
          if isAlphaNum c
          then f cs (c:wa) ta
          else f cs [] $ if length wa > 0 then [c]:(reverse wa):ta else [c]:ta

使用break没有用。我认为使用break和span的相互递归会起作用,但在我考虑尝试之前,我使用了上面的代码。

然后我按如下方式实现了complexObfuscation:

complexObfuscation exceptions g = unlines . map obfuscateLine . lines
  where obfuscateLine = concatMap obfuscateWord . words'
        obfuscateWord word =
          if word `elem` exceptions
          then word
          else obfuscate g word

这完成了我的目标。不幸的是,我没想到同一个生成器会在每次调用混淆时产生相同的字符。所以每个单词都以相同的字符开头。大声笑。另一天的问题。

1 个答案:

答案 0 :(得分:1)

阅读例外文件并构建Data.Set.Set

将输入文件拆分为lines后,将其进一步拆分为words

然后,单独模糊每个单词。如果某个单词是您之前构建的elem Set,请保持原样。否则,将obfuscate函数应用于每个字符。