K#er&ymjvw…-vp€‹?4^6zy‡:‰‹‘>“…ŽC”›G˜¡K™¢‘—PzR”¡?W™¦Z¤ª]ª®¶¦bº¹®g¼±¯k¹¼ÁÃp³·´ÉÉ¿½ÍÅzÂÅÏÊÁÕ‚×ÌʆÌÉÛÞÓŒ¶ŽâçÖÓå”éÞܘæéîðîîìêöè¤ôôì´©ýóñ÷Ă°þċ³ćĄċă¸ČĂĀ¼Ćđ¿čĚÂĚėĒċÈ÷ùËûûóÏĜĠĨĘħÕģĜØĚĭÛįĥģßĤİħĶäĕçėėďëďĎĜïŀŇĶļõŃļøĺûŏŅŃÿŐŇŖĐąĴŖĈŘŘŐČŐŏŝĐŔœťŦŮĖŤŝęśŮĜŰŦŤĠťűŨŷijĴħőĩŲźżŲĮƃſıſŴƆƇƏķƀžƌĻƏƌƍƍŌŁŃƇƆƔŇƖƘƞŋƣƎƗƣŜőŻœƞƪƩƫŘưƛƩưŝƲƮŠƴƲƨƲƩŦƬƾƮƼDŽŬƺƽƼƵƿdžųNjƾNJƿŸǁƿǍƊŽƦǀǂǃDŽDždžLJLjljNJNjnjǍƎƸƐǝǡǩǙƕǯǦǭƥƚDŽƜǞǢǮDzǦƢǼdzǺƲƧǪǸǬǭǮǯǰDZDzdzǴƴǞƶǺǹȇƺȃȁǾȐƿșȐȗȕDŽȍȋȈȚȝNJȌȚȑȜșȟȗǓȦȚȩȧȧȧȞȮȱȭǟȹȰȷȵȷDZǦȫȷǩɃȺɁǭɀȴȽȶȿȵȹɇǶɋɀȾǺɁɅɏɓȀɕɋɐɉȅȯȇɛɊɓɏȌɝȏɩɠɧȓȽȕɢɦɮɞȚɴɫɲȪȟɷɦȢɺɩɷɫȧɱɷȪɱɾɼɼʃȰʀɸȳʁʎȶɿʇʆɿȥɤɾʌʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥɱɦʐɨʵʹˁʱɭʾ˅ɱɺʿɽ
Great offer, If I found at least 40 distinct comments, I'd decrypte it :D
Monday, February 26, 2007
Poor message to my dear love
No Nooo, it's not encoding problem, it's encrypted message to my love and I am challenging "NO ONE CAN READ IT"
Subscribe to:
Post Comments (Atom)
22 comments:
there are double 3 mosh 3wzeen 7'm b2a :D:D
@Nabil
sure, I'll isA
@Anonymouse
do not cheat :D
@Hanaa
thnx for ur notice :D
سيبصراحه مش عارف بس ديه لغه عفاريتى خالص
@Omar (Islamic world)
ma enta mish ha t3rf t2raha omal hya lih encrypted :D
We need more hints.
What I reached till now is that maybe the the decryption depends on the character position, like you add a larger value as you move on. But I didn't figure out enough to decrypt it yet
Just, try ;-)
انا واثق ان دي مش رساله حقيقيه لانها نتتكون من كذا لغه .
انت رايك ايه يا رامي في الكلام دا ؟؟؟؟؟
@Nabil
I am sorry, I've deleted your comment by mistake !
@Ahmed Essawy
laa walahy ya abo 3essawy dih resala 7a2y2ya :)
enta ya 3am ramy enta,
etsraf el code ba2a m3a2ad we lessa mesh la2y el 7al, give one hint, just one
here is the code to convince u :
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <list>
using namespace std;
/************************
TYPEDEFS
*************************/
typedef std::binary_function<char,char,char> decryptor;
/************************
DEFINES
*************************/
#define DEFINE_DECRYPTION(DEC_NAME,OP) \
class DEC_NAME : public decryptor{\
public:\
decryptor::result_type operator()(decryptor::first_argument_type a,decryptor::second_argument_type b) const\
{ return OP ; }\
};
#define DEFINE_LOOP_DECRYPTION(DEC_NAME,OP) \
class DEC_NAME : public decryptor{\
int i;\
public:\
decryptor::result_type operator()(decryptor::first_argument_type a,decryptor::second_argument_type b) const\
{ return OP ; const_cast<DEC_NAME*>(this)->i++; }\
DEC_NAME():i(0){}\
};
#define len 50
/************************
DECRYPTORS
*************************/
DEFINE_DECRYPTION(_xor, a^b)
DEFINE_LOOP_DECRYPTION(_loop_minus, (char)((long)a-b-i) )
DEFINE_LOOP_DECRYPTION(_loop_xor, (char)((long)a^(b+i)) )
DEFINE_LOOP_DECRYPTION(_loop_plus, (char)((long)a-b+i) )
/************************
GLOBALS
*************************/
char data[2048];
/************************
FUNCTIONS
*************************/
bool check_valid(char* data)
{
//for(int i = 0; i < min(50,(int)strlen(data)); i++)
{
//if (isalnum(data[i]) || isspace(data[i]))
//continue;
//return false;
}
return true;
}
template <class t>
void apply_decryption(t functor)
{
char tmp[2048];
for (char i = 0x0; i < CHAR_MAX; i++)
{
strncpy(tmp,data,2048);
transform(tmp,tmp+strlen(tmp),tmp,bind2nd(functor,i));
for(int z = 0; z < len; z ++) if(tmp[z] == 0) tmp[z] = 1;
tmp[len] = 0;
if(!check_valid(tmp)) continue;
cout <<"\n\n\n\t" << typeid(functor).name() << " - trial " << (int)i << ":\n" << tmp;
}
}
/************************
MAIN
*************************/
int main()
{
ifstream inp("input.txt");
*data=0;
while (!inp.eof())
{
inp.getline(data+strlen(data),2048-strlen(data));
}
/********************************/
data[len+1] = 0;
/********************************/
cout << "original:\n" << data;
apply_decryption(plus<char>());
apply_decryption(minus<char>());
apply_decryption(_xor());
apply_decryption(_loop_minus());
apply_decryption(_loop_xor());
apply_decryption(_loop_plus());
return 0;
}
I found a bug here :$
{ return OP ; const_cast<DEC_NAME*>(this)->i++; }\
So i'll correct it and see :$
disregard the code state, i haven't had clean it yet...
Here's the code after cleaning and commenting and fixing 3 or 4 bugs :S
/*
* File: decrypt.cpp
* Description: A program to trial to decrypt Ramy's secret message
* Author: Mohammad Nabil
*/
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <list>
using namespace std;
/************************
TYPEDEFS
*************************/
// Define the number of trials counter datatype.
typedef unsigned char TrialNumber_t;
const int TrialNumberMax = UCHAR_MAX;
// Define the base for our functors.
// They take 2 params (binary_function duh!)
// Note that the number of trials is limited to UCHAR_MAX.
typedef std::binary_function< char /*ret_type*/ , char /*ch*/ , TrialNumber_t /*trial_no*/ > Decryptor;
/************************
DEFINES
*************************/
// A macro to define a decryption functor.
// It also adds a character counter facility.
#define DEFINE_DECRYPTION( DEC_NAME , OP ) \
class DEC_NAME : public Decryptor \
{ \
protected: unsigned int ch_index; \
public: Decryptor::result_type operator() \
( Decryptor::first_argument_type _ch , \
Decryptor::second_argument_type trial_no ) \
const \
{ \
const_cast<DEC_NAME*>(this)->ch_index++; \
if(0 == trial_no) \
const_cast<DEC_NAME*>(this)->ch_index=0;\
unsigned char ch = (unsigned char)_ch; \
return (OP) ; \
} \
DEC_NAME():ch_index(0){} /*Init character counter with zero*/\
};
// Define the length of the string to process.
const unsigned int len = 50;
/************************
DECRYPTORS
*************************/
// These decryptor functors will be able to use 3 variables:
// 1- ch, the current character to be processed.
// 2- trial_no, the trial number.
// 3- the current character index.
// These two are the duplicates of the plus and minus in STL,
// because unsigned char arithmetic!
DEFINE_DECRYPTION(
Plus,
ch + trial_no)
DEFINE_DECRYPTION(
Minus,
ch - trial_no)
// This is a simple char-by-char xor decryptor.
DEFINE_DECRYPTION(
Xor,
ch xor trial_no)
// This decryptor xors incrementally.
/* Example:
Trial 0: ^0 ^1 ^2 ...
Trial 1: ^1 ^2 ^3 ...
*/
DEFINE_DECRYPTION(
Loop_xor,
ch xor (trial_no+ch_index) )
// This decryptor adds incrementally.
/* Example:
Trial 0: -0 +1 +2 +3 +4 ...
Trial 1: -1 +0 +1 +2 +3 ...
*/
DEFINE_DECRYPTION(
Loop_plus,
ch+ch_index-trial_no )
// This decryptor subtracts incrementally.
// It uses the trial_no as a guide for the starting value to subtract.
/* Example:
Trial 0: -0 -1 -2 ...
Trial 1: -1 -2 -3 ...
*/
DEFINE_DECRYPTION(
Loop_minus,
ch-ch_index-trial_no )
/************************
GLOBALS
*************************/
// It assume it's a good practice to keep global data in namespaces so they don't
// get used by mistake uninentionally.
namespace GlobalData
{
// This holds the read string.
char input_string[2048];
}
/************************
FUNCTIONS
*************************/
// Retun false if there is any unprintable(garbage) characters
// in the 'str'. These characters indicate unsuccessful decryption.
bool check_valid(char* str)
{
for(unsigned int i = 0; i < min(len,(unsigned int)strlen(str)); i++)
{
if (isprint(str[i]))
continue;
return false;
}
return true;
}
template <class decryptor>
void apply_decryption(decryptor functor)
{
char tmp[sizeof(GlobalData::input_string)];
// trial_index must start at zero cuz the decryptor depends on that to
// reset it's internal character counter.
for (TrialNumber_t trial_index = 0x0; trial_index < TrialNumberMax; trial_index++)
{
// Work on a local copy so we don't change the original.
strncpy(tmp,GlobalData::input_string,2048);
// Apply the decryptor on all characters.
transform(tmp,tmp+strlen(tmp),tmp,bind2nd(functor,trial_index));
// Reduce to the size of required text.
tmp[len+1] = 0;
// If unsuccessful decryption; move on.
if(!check_valid(tmp)) continue;
cout <<"\n\n\n\t" << typeid(functor).name() << " - trial " << (unsigned int)trial_index << ":\n" << tmp;
}
}
/************************
MAIN
*************************/
int main()
{
ifstream inp("input.txt");
*GlobalData::input_string=0;
while (!inp.eof())
{
inp.getline(GlobalData::input_string+strlen(GlobalData::input_string),2048-strlen(GlobalData::input_string));
}
/********************************/
GlobalData::input_string[len+1] = 0;
/********************************/
cout << "original:\n" << GlobalData::input_string;
apply_decryption(Plus());
apply_decryption(Minus());
apply_decryption(Xor());
apply_decryption(Loop_minus());
apply_decryption(Loop_xor());
apply_decryption(Loop_plus());
return 0;
}
Here is the output I get:
-------8<--------
original:
K#er&ymjvw…-vp€�‹?4^6zy‡:‰‹‘>“…
4Plus - trial 181:
4Plus - trial 221:
(
5Minus - trial 35:
(
5Minus - trial 75:
3Xor - trial 35:
h
3Xor - trial 75:
3Xor - trial 101:
.F
10Loop_minus - trial 182:
10Loop_minus - trial 223:
)
8Loop_xor - trial 33:
i
8Loop_xor - trial 74:
8Loop_xor - trial 98:
(G
9Loop_plus - trial 37:
'
9Loop_plus - trial 76:
-------8<--------
c'mon ramy just one hint ... 7'aleed tayyeb :D
@mohammed nabil:
Why you're coding in this style?
Usually people use macros and inline class/function generation in generated code which won't be read by human and in huge project to make it easier and not to duplicate code, but in your code below I just see that the whole idea, also putting global data in their name space, it's not good, because it make the code very hard to be understood, you can use a valid naming convention for something like this (like prefixing your global variables with g_ as example), just an advice, this code is considered to be a type of obfuscated code which in big projects will be very bad because this is the hardest coding style to maintain and to debug.
Good code is not about creating templates for everything, the characteristic of good code is that which will be readable, easy to maintain and to debug and at the same time optimized.
If you like designing it by creating templates for every block of code which will have nearly the same functionality but in different way (this is the only reason I see of why you wrote the code in this way as your operations are sharing very common computations), the nearest thing I see to your code in this file is the factory pattern, it may not be a factory pattern but it seems to share the goal for the factory pattern.
Anyway, just as advice, try to minimize coding in this style as much as you can, it make code maintenance and debugging like hell, sometimes you need to sacrifice a very few extra cycles on the CPU to make the program design better, there’s always some more place for a bit more of optimization, like “if(x == 0) and if (0 == x)” believe it or not the second one is better than the first one because it doesn’t create a temporary object (this is something in the standard language specs which may not exist in all compilers), but you can scarify those extra cycles for the sake of making it readable.
I hope you got what I mean
I meant the "code above" not "code below" the problem that when I was writing the comment it was below :D
meshref:
Thanks for the hints. Anyway code maintainability was not a design goal while writing this code :D. My design goal was to minimize typing (ACM mood :D ) :D
I admit the code looks obfuscated and definitely this is not the way I'll write code for big application.
About the factory pattern, I didn't go through design phase asasan :D I started implementing 3alatool as I know this code is a draft anyway (that doesn't mean I don't usually go through design phase but it means that this was a toy code :D ).
The idea of putting the global data namespace is the same as putting g_, but I always hated the look of variables with underscores, so I thought about using a namespace.
About 0 == x, I didn't do it for optimization but cuz in C++ u can make if(x = 0) by mistake, instead if(0 = x) will generate an error. (And indeed I don't have unit tests to clear that out)
I said g_ as example, you can use "g" only, or global, or any standard prefix for all your code
As encapsulating stuff which don't need to be encapsulayed make it harder :)
By the way, ACM mode will make you write code which is not either designed nor compact :D
أترك تعليقك