Breaking a Modified Vigenere Cipher - security

Im working on an algorithm to break a modified Vigenere Cipher. The regular Vigenere cipher works in the following way:
Plaintext: ATTACKATDAWN
Key: LEMONLEMONLE
Ciphertext: LXFOPVEFRNHR
Regular Version
CR[i] = (P[i] - 33 + K[i]) mod 94 + 33
Modified Version
CM[i] = (P[i] - 33 + K[i] + CM[i-1] - 33) mod 94 + 33
Notice how the modified version uses previous state/character to generate the new one. My theory to break it is to reverse the modified version back to the regular Vigenere cipher. This way I can apply some frequency analysis and other methods. I need to somehow rearrange that equation such that I have "previousC" on the LHS with C. Since both C and previousC are known values it should be easy to do the reversal (starting with the first character).
My only problem is, how do I rewrite the equation in terms of C and previousC? If someone could point that out that would help a lot.

CR represents the regular Viginere ciphertext, CM the modified Viginere ciphertext
CR[i] = (P[i] + K[i]) mod 26
CM[i] = (P[i] + K[i] + CM[i-1]) mod 26
= (CR[i] + CM[i-1]) mod 26
Now simply solve for the original ciphertext CR
CR[i] = (CM[i] - CM[i-1]) mod 26
Once you have the regular ciphertext, break it as usual.

Related

How to write loop so that cipherkey can be greater than 26?

I need the cipher key to be able to be infinitely bigger than just the size of the alphabet (26) but still have a final key between 1-26
I am thinking about something like this:
if cipherKey > 26 and :
cipherKey = cipherKey - 26
But I think using a for loop to add the infinitely bigger condition so that if the cipher ends up being infinite + 26 the key will just be 26.
For example if the key is 30, then the cipher key is just 4.
Here is a simple solution
cipherKey = cipherKey%26

Not Returning ASCII characters when encrypting

I am trying to write an encryption code using Python. It encrypts but it does not use the ASCII characters and I am not sure why. I am very new to python and would love some help
def encrypt(text, shift):
cipher=""
for char in range(len(text)):
char = text[char]
if (char.isupper()):
cipher += chr((ord(char) + shift - 65) % 26 + 65)
else:
cipher += chr((ord(char) + shift - 97) % 26 + 97)
return cipher
It is encrypting but not returning ASCII characters
The formula
enc = (char + shift - offset) % m + offset
implicitly defines an alphabet within whose boundaries the encryption takes place, i.e. a character within this alphabet is mapped to another character of this aphabet. For example, the uppercase letters have an offset of 65 and a modulus of 26 (number of characters in the alphabet). This defines the alphabet as the range between 65 (A) and 65 + 26 - 1 = 90 (Z). A character between incl. A and Z is always mapped to a character between incl. A and Z and never to a character outside the alphabet. The same applies to lowercase letters. For this reason:
print("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
print(encrypt("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5));
results in the output:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
FGHIJKLMNOPQRSTUVWXYZABCDEfghijklmnopqrstuvwxyzabcde
If the special characters are also to be included, the range must be choosen accordingly, e.g. as a contiguous range between incl. 32 (Space) and incl. 126 (~). This corresponds to an offset of 32 and a modulus of 126 - 32 + 1 = 95 (number of characters in alphabet). The if-statement is no longer necessary because of the contiguous range, so that simply applies:
cipher += chr((ord(char) + shift - 32) % 95 + 32)
The following code:
print(" !\"#$%&'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~");
print(encrypt(" !\"#$%&'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", 5));
then produces the output:
!"#$%&'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
%&'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ !"#$
which now also contains the special characters.

How can i deobfuscate this text?

I've recently found some lua code and what I found inside was some obfuscated string. That made me wonder what sort of obfuscation technique was used there. Does anybody have an idea?
240.06230.0575240.06240.06270.0675250.0625265.06625270.0675250.0625285.07125260.065260.065260.065250.0625265...
https://pastebin.com/raw/7RkxjWQw
If this string is splitted into xxx.yyyy... chunks (exactly three digits before decimal point), then multiply each number by 800/4001 (the results will be integer!), then convert these integer numbers to ASCII, the hidden sequence of 16 floating point numbers would be revealed:
0.0062562944425795
0.036286507766961
0.02127140110477
0.047547837763604
0.041291543321025
0.0025025177770318
0.011261329996643
0.018768883327738
0.017517624439223
0.042542802209541
0.037537766655477
0.016266365550707
0.0087588122196113
0.057557908871731
0.025025177770318
0.026276436658834
Is the puzzle stops here?
Or should we try to decipher it further?
Ok, we could multiply them all by 32767/41 (the results will be integer!)
5
29
17
38
33
2
9
15
14
34
30
13
7
46
20
21
Hmm, the puzzle seems to be really interesting...
Is it the end?
Just googled it.
That's the passwords encrypted, something Roblox-related
So, OP surely doesn't have decoder script :-)
Ok, finally did it.
function decode_password(encoded_password)
local result = ""
local buffer = ""
for x in encoded_password:gsub("%d%d%d%.", "\0%0"):gmatch"%Z+" do
x = math.floor(tonumber(x) / 5.00125 + 0.5)
if x ~= 95 then
buffer = buffer..string.char(x)
elseif buffer ~= "" then
x = math.floor(tonumber(buffer) * 799.195122 + 0.5)
result = result..("qazwsxedcrfjmik,o0 23456-=\\vtgbyhnul.p;;;/[']1789"):sub(x, x)
buffer = ""
end
end
return result
end
Example 1:
local p = '240.06230.0575240.06240.06270.0675250.0625265.06625270.0675250.0625285.07125260.065260.065260.065250.0625265.06625275.06875285.07125265.06625475.11875240.06230.0575240.06255.06375270.0675250.0625280.07270.0675265.06625240.06275.06875275.06875270.0675270.0675285.07125270.0675245.06125475.11875240.06230.0575240.06250.0625245.06125250.0625275.06875245.06125260.065240.06245.06125245.06125240.06260.065275.06875275.06875475.11875240.06230.0575240.06260.065275.06875265.06625260.065275.06875280.07255.06375275.06875275.06875270.0675255.06375270.0675240.06260.065475.11875240.06230.0575240.06260.065245.06125250.0625285.07125245.06125265.06625260.065255.06375255.06375250.0625245.06125240.06250.0625265.06625475.11875240.06230.0575240.06240.06250.0625265.06625240.06250.0625265.06625245.06125275.06875275.06875275.06875275.06875240.06255.06375245.06125280.07475.11875240.06230.0575240.06245.06125245.06125250.0625270.0675245.06125255.06375250.0625285.07125285.07125285.07125270.0675270.0675260.065255.06375475.11875240.06230.0575240.06245.06125280.07275.06875270.0675280.07280.07280.07255.06375255.06375250.0625275.06875275.06875255.06375280.07475.11875240.06230.0575240.06245.06125275.06875265.06625245.06125275.06875270.0675250.0625260.065260.065255.06375285.07125250.0625250.0625255.06375475.11875240.06230.0575240.06260.065250.0625265.06625260.065250.0625280.07240.06250.0625250.0625240.06285.07125265.06625260.065245.06125475.11875240.06230.0575240.06255.06375275.06875265.06625255.06375275.06875275.06875270.0675270.0675270.0675265.06625265.06625260.065275.06875275.06875475.11875240.06230.0575240.06245.06125270.0675250.0625270.0675270.0675255.06375270.0675265.06625265.06625265.06625240.06275.06875240.06275.06875475.11875240.06230.0575240.06240.06280.07275.06875265.06625280.07280.07245.06125250.0625250.0625245.06125285.07125270.0675245.06125245.06125255.06375475.11875240.06230.0575240.06265.06625275.06875265.06625265.06625275.06875285.07125240.06280.07280.07275.06875245.06125275.06875255.06375245.06125475.11875240.06230.0575240.06250.0625265.06625240.06250.0625265.06625245.06125275.06875275.06875275.06875275.06875240.06255.06375245.06125280.07475.11875240.06230.0575240.06250.0625270.0675250.0625275.06875270.0675260.065255.06375270.0675270.0675265.06625280.07280.07255.06375260.065475.11875'
print(decode_password(p)) --> stophackingme123
Example 2:
for _, info in ipairs(loginDatabase) do
print(info.username, decode_password(info.password))
end

Node.js Crypto, what's the default padding for AES?

I've traversed the Node.js Crypto documentation but still couldn't find the default padding used by the Cipher class, for example the method cipher.setAutoPadding(true) has no specification about it. So is it PKCS#5, PKCS#7...?
Any info on this will be great!
In the documentation (https://nodejs.org/api/crypto.html#crypto_cipher_setautopadding_autopadding) it says:
Disabling automatic padding is useful for non-standard padding, for instance using 0x0 instead of PKCS padding.
So it's using "PKCS". More specifically, PKCS7.
PKCS7 defined the same padding algorithm that PKCS5 did, but PKCS5 assumed all ciphers would have 8 byte (64 bit) block sizes. PKCS7's version describes it as a k-byte block. In practice, people ignore that PKCS5 had a fixed block size, and "PKCS5 padding" and "PKCS7 padding" are the same thing.
PKCS5 (https://www.rfc-editor.org/rfc/rfc2898#section-6.1.1):
4. Concatenate M and a padding string PS to form an encoded
message EM:
EM = M || PS ,
where the padding string PS consists of 8-(||M|| mod 8) octets
each with value 8-(||M|| mod 8). The padding string PS will
satisfy one of the following statements:
PS = 01, if ||M|| mod 8 = 7 ;
PS = 02 02, if ||M|| mod 8 = 6 ;
...
PS = 08 08 08 08 08 08 08 08, if ||M|| mod 8 = 0.
PKCS7 (https://www.rfc-editor.org/rfc/rfc5652#section-6.3):
Some content-encryption algorithms assume the input length is a
multiple of k octets, where k is greater than one. For such
algorithms, the input shall be padded at the trailing end with
k-(lth mod k) octets all having value k-(lth mod k), where lth is
the length of the input. In other words, the input is padded at
the trailing end with one of the following strings:
01 -- if lth mod k = k-1
02 02 -- if lth mod k = k-2
.
.
.
k k ... k k -- if lth mod k = 0

block cipher in CTR mode manipulation

I have a question about block cipher using CTR mode. I think i need to find something (value) that when I do 46 XOR value = 43, I get value to be (1011 1101), then i use 0x64(0110 0100) XOR value(1011 1101) but it does not give me 0x72(0111 0010). Did I miss something here? My upstanding is that in order to do this, all i need to do is to find a value that adds counter (in this case is zero) and xor the plain text to get cipher text. Did I miss something here? Thank you in advance.
You know that the 2nd and 3rd block were created by the same key stream (created by concatenating the counter values encrypted by the block cipher).
So for the first byte of the second block you'd have 46 = 43 ^ KK and 51 = P2 ^ KK where KK is the first byte of the key stream. Now KK can be easily calculated, as KK = 46 ^ 43 (KK = 05 if I'm not mistaken). Now P2 = KK ^ 51 or P2 = 05 ^ 51 = 54.
You can simply repeat that for each index into the streams and presto. You don't have to do anything with the counter itself; knowing that the same key and counter were used is enough to generate the same key stream.

Resources