pezcurrel 7 kuukautta sitten
commit
42697411da
4 muutettua tiedostoa jossa 454 lisäystä ja 0 poistoa
  1. 63 0
      README.md
  2. 391 0
      decrypt
  3. BIN
      english.txt.xz
  4. BIN
      italiano.txt.xz

+ 63 - 0
README.md

@@ -0,0 +1,63 @@
+```text
+SYNOPSIS
+
+decrypt -d <dictionary file> <phrase>
+
+DESCRIPTION
+
+This is decrypt v0.1, a CLI PHP script that can help decrypting
+phrases encrypted with any algorithm producing an encrypted phrase where each
+symbol always replaces the same, different symbol from the clear text one.
+
+COMMAND LINE OPTIONS
+
+-d, --dictfp <dictionary file>
+ Load a dictionary file. It has to be a simple text file with one word on each
+ line. You have to specify at least one, and you can specify more than one
+ prepending «-d» or «--dictfp» to each file path.
+ Currently decrypt comes with two xz compressed dictionary files:
+ «english.txt.xz» and «italiano.txt.xz». To use any of them, you have to
+ decompress it with the xz program. They both are dumps from the corresponding
+ aspell dictionaries, with each lemma declined in all its forms. You can
+ get dumps for other languages with something like this:
+ aspell -d <lang code> dump master | aspell -l <lang code> expand 4
+ (You may need to further process the above command output with tr, grep, sed
+ and the likes, in order to have a functional dictionary file).
+-n, --normalize
+ “Normalize” each dictionar(y|ies) entry replacing every accented or otherwise
+ “signed” character with its “plain” form, and removing possible duplicated
+ entries. For example, this will substitute every “è” character with “e”.
+-e, --encrypt
+ Encrypt the given phrase. Useful for testing purposes. By default, or when
+ «-m» or «--method» is set to «0», it encrypts the phrase by simply switching
+ every source character with its subsequent character in the UTF-8 table. With
+ «-m» or «--method» set to «1», it encrypts the phrase using a random
+ substition table.
+-m, --method <0|1>
+ Choose a method for encryption when «-e» or «--encrypt» is specified (see
+ previous option description). It defaults to “0”.
+-p, --progress
+ Show progress during script execution.
+-w, --write
+ Write any substition table decrypt may find into a «substable.txt»
+ file and any solution decrypt may find into a «solutions.txt» file.
+ Both files will be written in current working directory. Note that possible
+ existing files with the same name will be overwritten.
+-h, --help
+ Show this help text and exit.
+
+EXAMPLE
+
+decrypt "rûéï eïw6ï w 6fwh6ï" -d english.txt -p -w
+
+Will produce 983 solutions, with «give peace a chance» being one of them,
+showing progress during the execution, writing substitution tables into
+«substable.txt» and solutions into «solutions.txt» within current working
+directory.
+
+DISCLAIMER AND LICENSE
+
+This program comes with ABSOLUTELY NO WARRANTY; for details see the source.
+This is free software, and you are welcome to redistribute it under certain
+conditions; see <http://www.gnu.org/licenses/> for details.
+```

+ 391 - 0
decrypt

@@ -0,0 +1,391 @@
+#!/usr/bin/php
+<?php
+
+/*
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+const SNAME='decrypt';
+const SVERS='0.1';
+
+$conf=[
+	'phrase'=>null,
+	'encrypt'=>false,
+	'method'=>0,
+	'write'=>false,
+	'norm'=>false,
+	'progress'=>false,
+	'substabfp'=>'substable.txt',
+	'solsfp'=>'solutions.txt',
+	'dictfps'=>[],
+	'debug'=>false
+];
+
+$help=
+'SYNOPSIS
+
+'.SNAME.' -d <dictionary file> <phrase>
+
+DESCRIPTION
+
+This is '.SNAME.' v'.SVERS.', a CLI PHP script that can help decrypting
+phrases encrypted with any algorithm producing an encrypted phrase where each
+symbol always replaces the same, different symbol from the clear text one.
+
+COMMAND LINE OPTIONS
+
+-d, --dictfp <dictionary file>
+ Load a dictionary file. It has to be a simple text file with one word on each
+ line. You have to specify at least one, and you can specify more than one
+ prepending «-d» or «--dictfp» to each file path.
+ Currently '.SNAME.' comes with two xz compressed dictionary files:
+ «english.txt.xz» and «italiano.txt.xz». To use any of them, you have to
+ decompress it with the xz program. They both are dumps from the corresponding
+ aspell dictionaries, with each lemma declined in all its forms. You can
+ get dumps for other languages with something like this:
+ aspell -d <lang code> dump master | aspell -l <lang code> expand 4
+ (You may need to further process the above command output with tr, grep, sed
+ and the likes, in order to have a functional dictionary file).
+-n, --normalize
+ “Normalize” each dictionar(y|ies) entry replacing every accented or otherwise
+ “signed” character with its “plain” form, and removing possible duplicated
+ entries. For example, this will substitute every “è” character with “e”.
+-e, --encrypt
+ Encrypt the given phrase. Useful for testing purposes. By default, or when
+ «-m» or «--method» is set to «0», it encrypts the phrase by simply switching
+ every source character with its subsequent character in the UTF-8 table. With
+ «-m» or «--method» set to «1», it encrypts the phrase using a random
+ substition table.
+-m, --method <0|1>
+ Choose a method for encryption when «-e» or «--encrypt» is specified (see
+ previous option description). It defaults to “'.$conf['method'].'”.
+-p, --progress
+ Show progress during script execution.
+-w, --write
+ Write any substition table '.SNAME.' may find into a «'.$conf['substabfp'].'»
+ file and any solution '.SNAME.' may find into a «'.$conf['solsfp'].'» file.
+ Both files will be written in current working directory. Note that possible
+ existing files with the same name will be overwritten.
+-h, --help
+ Show this help text and exit.
+
+EXAMPLE
+
+decrypt "rûéï eïw6ï w 6fwh6ï" -d english.txt -p -w
+
+Will produce 983 solutions, with «give peace a chance» being one of them,
+showing progress during the execution, writing substitution tables into
+«'.$conf['substabfp'].'» and solutions into «'.$conf['solsfp'].'» within current working
+directory.
+
+DISCLAIMER AND LICENSE
+
+This program comes with ABSOLUTELY NO WARRANTY; for details see the source.
+This is free software, and you are welcome to redistribute it under certain
+conditions; see <http://www.gnu.org/licenses/> for details.';
+
+// 4E E1V VXVTHM VP SRR 0AY DA23I5VO L 2W4T WL 9ONA1Z K5 HIDUFJ 88LC NZD4 S50B.
+
+// sempre caro mi fu quest'ermo colle
+// tfnqsf dbsp nj gv rvftu'fsnp dpmmf
+
+// e il naufragar m'è dolce in questo mare
+// f jm obvgsbhbs n'é epmdf jo rvftup nbsf
+// 6 v0 7òôõíò3òí x'à êú0ø6 v7 ûô6hwú xòí6 (casuale)
+
+for ($i=1; $i<$argc; $i++) {
+	if ($argv[$i]=='-h' || $argv[$i]=='--help') {
+		echo "{$help}\n";
+		exit(0);
+	} elseif ($argv[$i]=='--makereadme') {
+		file_put_contents(__DIR__.'/README.md',"```text\n{$help}\n```\n");
+		exit(0);
+	} elseif ($argv[$i]=='-e' || $argv[$i]=='--encrypt') {
+		$conf['encrypt']=true;
+	} elseif ($argv[$i]=='-d' || $argv[$i]=='--dictfp') {
+		if ($i<$argc-1) {
+			$i++;
+			$conf['dictfps'][]=$argv[$i];
+		} else {
+			edie("«{$argv[$i]}» requires an argument (use «-h» or «--help» for help); shutting down.\n",1);
+		}
+	} elseif ($argv[$i]=='-m' || $argv[$i]=='--method') {
+		if ($i<$argc-1) {
+			if (in_array($argv[$i+1],['0','1']))
+				$conf['method']=$argv[$i+1]+0;
+			else
+				edie("«{$argv[$i+1]}» is not a valid argument for «{$argv[$i]}» (use «-h» or «--help» for help); shutting down.\n",1);
+			$i++;
+		} else {
+			edie("«{$argv[$i]}» requires an argument (use «-h» or «--help» for help); shutting down.\n",1);
+		}
+	} elseif ($argv[$i]=='-w' || $argv[$i]=='--write') {
+		$conf['write']=true;
+	} elseif ($argv[$i]=='-n' || $argv[$i]=='--norm') {
+		$conf['norm']=true;
+	} elseif ($argv[$i]=='-p' || $argv[$i]=='--progress') {
+		$conf['progress']=true;
+	} elseif (is_null($conf['phrase'])) {
+		$conf['phrase']=trim($argv[$i]);
+	} else {
+		edie("a phrase has already been specified and «{$argv[$i]}» is not a known option (use «-h» or «--help» for help); shutting down.\n",1);
+	}
+}
+//print_r($conf); pause();
+
+if (is_null($conf['phrase']))
+	edie("you have not specified a phrase (use «-h» or «--help» for help); shutting down.\n",1);
+elseif ($conf['phrase']=='')
+	edie("you can’t specify an empty string as phrase (use «-h» or «--help» for help); shutting down.\n",1);
+
+if ($conf['encrypt']) {
+	$phrase=mb_strtolower($conf['phrase']);
+	if ($conf['method']==1) {
+		$ichars='aàáâãäåbcdeèéêëfghiìíîïjklmnoòóôõöøpqrstuùúûüvwxyz0123456789';
+		$len=mb_strlen($ichars);
+		for ($i=0; $i<$len; $i++)
+			$buff[]=mb_substr($ichars,$i,1);
+		$ichars=$buff;
+		shuffle($buff);
+		for ($i=0; $i<$len; $i++)
+			$ochars[$ichars[$i]]=$buff[$i];
+		$len=mb_strlen($phrase);
+		$buff='';
+		for ($i=0; $i<$len; $i++) {
+			$c=mb_substr($phrase,$i,1);
+			if (array_key_exists($c,$ochars))
+				$buff.=$ochars[$c];
+			else
+				$buff.=$c;
+
+		}
+	} elseif ($conf['method']==0) {
+		$buff='';
+		for ($i=0; $i<mb_strlen($phrase); $i++) {
+			$c=mb_substr($phrase,$i,1);
+			if ($c==' ')
+				$buff.=' ';
+			else
+				$buff.=mb_chr(mb_ord($c)+1);
+		}
+	}
+	echo "{$buff}\n";
+	exit(0);
+}
+
+if (count($conf['dictfps'])==0)
+	edie("you have specified no dictionaries (use «-h» or «--help» for help); shutting down.\n",1);
+$norma=[
+	'a'=>['à','á','â','ã','ä','å'],
+	'e'=>['è','é','ê','ë'],
+	'i'=>['ì','í','î','ï'],
+	'o'=>['ò','ó','ô','õ','ö','ø'],
+	'u'=>['ù','ú','û','ü']
+];
+$dict=[];
+foreach ($conf['dictfps'] as $fp) {
+	$buff=@file($fp,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
+	if ($buff===false)
+		edie("could not open dictionary file «{$fp}» (use «-h» or «--help» for help); shutting down.\n",1);
+	foreach ($buff as $k=>$v)
+		$conf['norm'] ? $dict[]=norm(mb_strtolower($v)) : $dict[]=mb_strtolower($v);
+}
+$dict=array_unique($dict);
+//shuffle($dict);
+foreach ($dict as $k=>$v) {
+	$len=mb_strlen($v);
+	$buff=[];
+	for ($i=0; $i<$len; $i++) {
+		$dc=mb_substr($v,$i,1);
+		if ($conf['method']==1)
+			$dc=mb_chr(mb_ord($dc)+$i);
+		$buff[]=$dc;
+	}
+	$dict[$k]=['len'=>$len,'splitword'=>$buff,'word'=>$v];
+}
+if (count($dict)==0)
+	edie("the dictionar(y|ies) you have specified contain(s) no words; shutting down.\n",1);
+//foreach ($dict as $k=>$v) echo "{$v['word']}\n"; die();
+
+$phrase=preg_replace('#\s+#u',' ',$conf['phrase']);
+$phrase=mb_strtolower($phrase);
+$cphrase=$phrase;
+$phrase=preg_split('#\W+#u',$phrase);
+//$phrase=explode(' ',$phrase);
+$buff=[];
+foreach ($phrase as $k=>$v)
+	$buff[$k]=mb_strlen($v);
+arsort($buff,SORT_NUMERIC);
+foreach ($phrase as $k=>$v) {
+	$len=mb_strlen($v);
+	$split=[];
+	for ($i=0; $i<$len; $i++)
+		$split[]=mb_substr($v,$i,1);
+	$buff[$k]=['len'=>$len,'splitword'=>$split,'word'=>$v,'sols'=>[]];
+}
+$phrase=$buff;
+//print_r($phrase); pause();
+
+$c=count($phrase);
+$d=0;
+$cns=0;
+$substa=[[]];
+foreach ($phrase as $pindex=>$pword) {
+	$d++;
+	$ib=$pindex+1;
+	eprog("Working on phrase word {$ib}: «{$pword['word']}» ({$d}/{$c})\n");
+	$newsubsta=ckdict($dict,$pword,$pindex,$substa);
+	/*foreach ($newsubsta as $k=>$v)
+		echo strsubsta($v)."\n";*/
+	$cns=count($newsubsta);
+	eprog("Finished working on phrase word {$ib}: «{$pword['word']}» ({$d}/{$c}); found {$cns} compatible keys.\n");
+	//pause();
+	if ($cns==0) break;
+	$substa=$newsubsta;
+	unset($newsubsta);
+	/*if ($conf['progress']) {
+		foreach ($substa as $subst) {
+			$out='';
+			foreach ($xphrase as $pword) {
+				$out.=getsubst($subst,$pword['word']).' ';
+			}
+			$out=substr($out,0,-1);
+			//echo strsubsta($subst)."\n";
+			echo "{$out}\n";
+		}
+		echo "---\n";
+		pause();
+	}*/
+}
+if (count($substa)>0) {
+	if ($conf['write'])
+		if (false===file_put_contents($conf['substabfp'],print_r($substa,true)))
+			eerr("Warning: could not open «{$conf['substabfp']}» for writing.\n");
+	//ksort($phrase,SORT_NUMERIC);
+	$i=0;
+	if ($conf['write']) {
+		$f=@fopen($conf['solsfp'],'w');
+		if ($f===false)
+			eerr("Warning: could not open «{$conf['solsfp']}» for writing.\n");
+	}
+	foreach ($substa as $subst) {
+		$i++;
+		$oline=$i.': '.getsubst($subst,$cphrase)."\n";
+		eprog($oline);
+		if ($conf['write'] && $f!==false) fwrite($f,$oline);
+	}
+	if ($conf['write'] && $f!==false) fclose($f);
+	if ($cns==0) echo "Warning: no complete solutions found.\n";
+} else {
+	echo "No solutions found.\n";
+}
+exit(0);
+
+function ckdict(&$dict,$pword,$pindex,$substa) {
+	global $phrase, $conf;
+	$newsubsta=[];
+	foreach ($dict as $dword) {
+		if ($dword['len']==$pword['len']) {
+			//echo "«{$pword['word']}» has same length as «{$dword['word']}»\n";
+			foreach ($substa as $subst) {
+				$newsubst=$subst;
+				//echo '-> '.strsubsta($newsubst)."\n";
+				$ok=true;
+				for ($i=0; $i<$pword['len']; $i++) {
+					$pc=$pword['splitword'][$i];
+					$dc=$dword['splitword'][$i];
+					//$dc=mb_chr(mb_ord($dword['splitword'][$i])+$i);
+					$x=array_search($dc,$newsubst,true);
+					if (($x!==false && $x!=$pc) || (array_key_exists($pc,$newsubst) && $newsubst[$pc]!=$dc)) {
+						$ok=false;
+						break;
+					}
+					$newsubst[$pc]=$dc;
+				}
+				if ($ok) {
+					if ($conf['progress'] && !in_array($dword['word'],$phrase[$pindex]['sols'])) {
+						$phrase[$pindex]['sols'][]=$dword['word'];
+						echo "«{$pword['word']}» could be «{$dword['word']}»\n";
+					}
+					$newsubsta[]=$newsubst;
+				}
+			}
+		}
+	}
+	return $newsubsta;
+}
+
+function eprog($str) {
+	global $conf;
+	if ($conf['progress'])
+		echo $str;
+}
+
+function eerr($str) {
+	fwrite(STDERR,$str);
+}
+
+function pause() {
+	echo "Press return to continue ";
+	fgets(STDIN);
+}
+
+function getsubst($subst,$str) {
+	$out='';
+	$len=mb_strlen($str);
+	for ($i=0; $i<$len; $i++) {
+		$sc=mb_substr($str,$i,1);
+		//$sc=mb_chr(mb_ord(mb_substr($str,$i,1))+$i);
+		if (array_key_exists($sc,$subst))
+			$out.="\33[0;7m{$subst[$sc]}\33[0;0m";
+		else
+			$out.=$sc;
+	}
+	str_replace("\33[0;0m\33[0;7m",'',$out);
+	return $out;
+}
+
+function norm($str) {
+	global $norma;
+	$out='';
+	$len=mb_strlen($str);
+	for ($i=0; $i<$len; $i++) {
+		$sc=mb_substr($str,$i,1);
+		//echo "sc: {$sc}\n";
+		$nc=$sc;
+		foreach ($norma as $k=>$nnca)
+			if (in_array($sc,$nnca)) {
+				$nc=$k;
+				break;
+			}
+		$out.=$nc;
+	}
+	return $out;
+}
+
+function strsubsta($arr) {
+	$out='';
+	foreach ($arr as $key=>$val)
+		$out.="{$key}={$val}; ";
+	if (strlen($out)>0)
+		$out=substr($out,0,-2);
+	return $out;
+}
+
+function edie($msg,$ec) {
+	fwrite(STDERR,'Error: '.$msg);
+	exit($ec);
+}
+
+?>

BIN
english.txt.xz


BIN
italiano.txt.xz