• Forum
  • Lounge
  • Challenge: Questionable Encryption Algor

 
Challenge: Questionable Encryption Algorithm

Pages: 12
I remembered Ang from a few years ago creating a dumb encryption program. I was looking for something fun to do, figured I'd see if I'd have any better luck at cracking this dumb encryption than back then.

Since then, their company website is gone.. big surprise. It's even sadder considering I made a much better program in my spare time, using AES256 encryption and a GUI that I, at least, think is really good.

Anyway, now I wanna try to crack it again... tomorrow.

I sleep now.


Code thanks to Helios(!):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
bool encrypt(const byte *passphrase, byte *plaintext, int length)
{
	auto passphrase_length = strlen((const char *)passphrase);
	if (passphrase_length == 0)
		return false;

	std::uint32_t read_position = 0;
	std::uint32_t write_position = 0;
	byte x = (byte)*passphrase + 123;
	std::uint32_t y = 0;
	auto ciphertext = plaintext;
	while (write_position < length){
		ciphertext[write_position] = x = (byte)(x * 1.5) - (byte)(y % 13) + passphrase[read_position] + plaintext[write_position] - (byte)11;
		read_position = (read_position + 1) % passphrase_length;
		write_position++;
		y += 6;
	}
	return true;
}
Ah, a "blast from the past" post that was, and is, a delight to read; the arrogance of some people who resist mightily the rigors of reality.

Clearly all the OP wanted was to have a bunch of easily duped people worship them and their "coding-fu" (lack of) skills.
I think I've worked out a formula that will greatly untangle the encryption, I'll be trying it out after I come back from the gym.

Speaking of, I swear I'm dumber after hitting the gym. My brain must be on energy saving mode afterwards.
Well, its simple enough getting this far:

1
2
3
4
5
6
7
void decrypt(char* c, int s) //c is the cypher text
{
	for (int i = 1; i < s; i++)
	{
		cout << char(c[i] - (char)(c[i - 1] * 1.5) + (char)((i * 6) % 13) + 11);
	}
}


This will get you the plainText + Password combined strings, excluding the first letter. So if the text was "Hello World!" this would only be able to recover "ello World!" with this which is fine.

The output of my decrypt function would be the same as this:

1
2
3
4
5
void encrypt(string pass, string text)
{
	for (int i = 0; i < text.size(); i++)
		text[i] = text[i] + pass[i % pass.size()];
}


Simple addition of the text to the password string. I myself wouldn't know how to decrypt this, but obviously not secure.

First thought is to brute force with a password bank, but then getting this far didn't matter to begin with.


Obviously if you can get a known string encrypted you'd immediately know the password (as long as the string getting encrypted is at least longer than the password by 1).
Last edited on
Well, yea, the only thing I can think of would be to force the algorithm to encrypt a known text with the password, then getting the password out of the cipher text would be simple as pi:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
string encrypt(string pass, string text)
{
	std::uint32_t read_position = 0;
	std::uint32_t write_position = 0;
	char x = pass[0] + 123;
	std::uint32_t y = 0;

	string q = text;

	while (write_position < text.size())
	{
		q[write_position] = x = (char)(x * 1.5) - (char)(y % 13) + pass[read_position] + text[write_position] - (char)11;
		read_position = (read_position + 1) % pass.size();
		write_position++;
		y += 6;
	}

	return q;
}

string decrypt(string c)
{
	string a = c;
	for (int i = 1; i < c.size(); i++)
	{
		a[i] = char(c[i] - (char)(c[i - 1] * 1.5) + (char)((i * 6) % 13) + 11);
	}
	return a;
}

int main()
{
	string q = "Hello World!";
	string p = "PassWord";

	string crypt = encrypt(p, q);
	string dekrpt = decrypt(crypt);

	cout << "Encrypted:\n" << crypt << "\n\n";
	cout << "Decrypted:\n" << dekrpt << "\n\n";

	cout << "Get Original Password:\n";
	for (int i = 1; i < dekrpt.size(); i++)
	{
		cout << char(dekrpt[i] - q[i]);
	}
}


Encrypted:
>↕πñ&╣J4ⁿ║[►

Decrypted:
>╞▀▀╞Å╔╙┬═╫ö

Get Original Password:
assWordPass


First letter of password wont appear the first time, but the password will loop which will give away its beginning and end.



Wasn't as fun as I hoped ;(
Last edited on
I am not at all versed in encryption theory and how difficult breaking X is.
but a 3 line program that both encrypts and decrypts I have no clue how to break...

cin 64 bit int password or convert text input to 64 bit password via sha-like something
seed <random> with password
xor all data with random number from seeded stream

Ive used the like a lot over the years for what I consider "level 1" security, just enough to discourage idiots and power users from stealing something of minimal value. Its only real flaw is that text file input -> binary file output, if you care. Bonus, every compiler and possibly even versions of same compiler changes the result (due to how their random library is implemented) (making it not so good for commercial use, but fine for lazy coders).
I've found that using an encryption library can be really easy. I created encryption software in my free time and making the GUI look nice took up the most time! I wanted it to be top notch security, so I honestly went a little overboard with the safety features.. Did a lot of research to make it safe against brute force password guessing.

But people see the anime girl design and don't wanna use it LOL. I should really give it a new theme... eventually.


This reminds me of my horrific algorithms professor and what he thought to be "safe" practices for security.

Its only real flaw is that text file input -> binary file output

I think there's no getting around the when encrypting data.
I know its probably flawed in some way. Its just cool that its pretty strong for 3 lines of effort. If someone knows a flaw with it, I would love to know more, even though really, all its meant to do is keep bored nosey co-workers or the like out or to transmit a low security zip/image/etc via email to myself.

Going all in works too, but its a moving target and a challenging field where you have people actively trying to undo your hard work. We thought 256 bit was pretty good too, once :) I predict it falls in another decade or so.
Last edited on
Its just cool that its pretty strong for 3 lines of effort

Let's see it 0-0

We thought 256 bit was pretty good too, once :)

256 bit is thought to be able to withstand quantum computers too, so I'm pretty sure it's still considered great!

My program you can just drag-in-drop the file right into the application, type in a password, and it'll be encrypted. Drag-in-drop the encrypted file into to application on another computer, give it the password, and it'll decrypt it. Only takes a second.
cin 64 bit int password or convert text input to 64 bit password via sha-like something
seed <random> with password
xor all data with random number from seeded stream

Thinking about it, this provides basically the same kind of protection that this encryption algorithm provides.

If someone has the cypher text of your program where they know some or all of the original file's contents, they'll be able to work out the password you used to encrypt it - then they can decrypt the whole file and any other file you encrypted with that password.

This kind of attack was used against Hitler (I've read) where they knew that enemy messages always ended in "Hail Hitler" which allowed them to decode the rest of the cypher.

Modern encryptions, like AES, make it unpractical to try and crack it this way. Even if you encrypted a fully known message, you'd still be better off trying every password combination rather than reverse engineering the cypher.
Last edited on
I think what Jonnin is describing is roughly
1
2
3
srand(key)
for each byte c in the input buffer
  print c ^ (rand() & 0xff) to the output buffer

If someone has the cypher text of your program where they know some or all of the original file's contents, they'll be able to work out the password you used to encrypt it - then they can decrypt the whole file and any other file you encrypted with that password.

When a truly-random key stream is combined intelligently with plain-text the encryption scheme is called a "one-time pad" and the result is provably secure. ("Combined intelligently" means modular addition of which bit-wise XOR is a special case.)

When a psuedo-random key stream is substituted for a truly-random key stream, the state of the PRNG becomes the "key". To recover that key, it might be possible to exploit the statistical properties of the PRNG in some way, but this could be a tall order, especially when the PRNG is chosen carefully.
Last edited on
Ahh I see, it becomes a matter of figuring out the workings of the RNG rather than simply figuring out a password.

I can't imagine this is impossible, but likely good enough.


Digging around, I found this:

https://github.com/eboda/mersenne-twister-recover


Given at least 624 outputs of a Mersenne Twister we can restore its internal state


So if you were able to encrypt 624 consecutive known characters, you could have the state of the RNG as if the proper seed had been given.

It's possible there are such tools for many other RNGs and doubtful there's an RNG algorithm immune to such reversal.
Last edited on
It's possible there are such tools for many other RNGs and doubtful there's an RNG algorithm immune to such reversal.

You could be right, but the idea of combining plaintext with a stream of psuedo-random numbers is used in real ciphers:
https://en.wikipedia.org/wiki/Salsa20
Normal PRNGs (pseudorandom number generators), e.g. "Mersenne Twister" or "Xorshift", are designed to be indistinguishable from "true" randomness in statistical tests, such as the "Diehard" suite, but not to withstand purposeful attacks. You'd use them for Monte Carlo experiments, etc, but not for cryptographic purposes!

For cryptographic purposes, you want a CSRNG (cryptographically secure pseudorandom number generator), which is designed specifically to withstand attacks, such as reconstruction of the internal state from the observed output, or predicting the future output from a compromised state. See "Fortuna" as an example:

https://www.schneier.com/wp-content/uploads/2015/12/fortuna.pdf
Last edited on
You'd use such PRNGs for Monte Carlo experiments and the like, not for cryptographic purposes.

True.

Sounds legit.
Yeah, C++ <random> may be better than the C library PRNG functions trivial and not-so-trivial purposes, but cryptography uses are seriously hard-core and need more robust randomness.
At a glance the randomness used in stream ciphers usually seems to be built from lots of simpler PRNGs chained together in particular ways. This is just what I've observed during far too little research.
Last edited on
this gave me a number of things to consider and research. Granted I am still just playing, I know better than to DIY on anything important, but its an on again off again hobby :)
Thanks for the ideas & discussion.
Encrypted:
>↕πñ&╣J4ⁿ║[►

Decrypted:
>╞▀▀╞Å╔╙┬═╫ö

Get Original Password:
assWordPass
Hahaha! You didn't even need a second ciphertext to recover almost all the password information!

>Its only real flaw is that text file input -> binary file output

I think there's no getting around the when encrypting data.
If you don't care about file size, you could encode the output into a sequence of words from a predefined dictionary. This is how BIP-39 encodes private key bits into a string easily copied by humans. E.g. "boring wolf accident add select anchor hope gossip correct jacket boring that vote cotton hope" encodes 64 bytes.
Last edited on
Pages: 12