commit 39c70c63864c728d3405729b7b0f7677034f81a8 Author: thecookingsenpai Date: Mon Dec 25 13:31:04 2023 +0100 Initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..18f1bb1 --- /dev/null +++ b/README.md @@ -0,0 +1,98 @@ +# xsacks +A crossed substitution alphabetical cipher with secured key + +# The sources + +Please note that the python implementation is still WiP (actually it works but miss some checks and features) + +You can import the xsacks.py module and use xsacks.cipher(msg, key, securekey) and xsacks.decipher(msg, key, securekey). + +If you modify xsacks.py, you can run a cipher-decipher test directly from the module, so to be sure you didn't screw things up. + +# X-SACK + +This cipher is based on crossed substitution of the message and on simple substitution of the key. Let’s explain it with an example. + +Our message is: msg = “Attack now” + +Our key is: key=”secret” + +Our secure-key (you’ll see the meaning later) is: skey=”cryp” + + +Before starting, you have to assign to each letter of the alphabet (and also to numbers and symbols if you use them) a number. In a software, it could be the ASCII value of the character. Let’s use a simple one as example, though it’s a valid one. + + +0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ? . + +0 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 + +First of all, you need to split msg separating each letter: + +a t t a c k _ n o w + +NOTE: space is a valid character, so i used “_” just to show it + +Now substitute to each letter its number: + +10 29 29 11 13 20 36 23 24 32 + +You’ll do the same thing with the key: + +s e c r e t + +28 14 12 27 14 29 + + +Now you have to split the key in two parts: + + +s e c | r e t + +28 14 12 | 27 14 29 + +Time to substitute! + +To perform a cross substition, add to the first msg value the first key value of the first group (a+s), then add to the second msg value the first key value of the second group (t+r), continue adding to the third msg value the second key value of the first group, then to the fourth msg value the second key value of the second group and so on. + + +Restart from the beginning if the key ends. + +Now you should reconvert numbers to letters. If the number exceed the limit of your alphabet, simple start counting from the beginning. + +Let’s decode: + +10 28 15 34 35 21 36 22 20 18 + +A S F Y Z L _ M K I + +The encrypted message is: ASFYZL_MKI + +Though is really hard to decode the message without having the key, even having a large amount of text, the last step is to encode also the key, with the secure key. +The steps are almost the same, but you don’t have to split the secure key. Simple substitute, check the values and then reconvert. + +S E C R E T + +28 14 12 27 14 29 + +C R Y P C R + +12 27 34 25 12 27 40 + +So, the encoded key is: 238EQI + +The only way to decrypt the message is having the msg, the encoded key and the secure key, or the plain key if you are so dumb to give the plain one. + +Give to your friend: + +ASFYZL_MKI + +238EQI + +CRYP + + + +And he will be able to read “attack now”. + + diff --git a/xsacks.py b/xsacks.py new file mode 100644 index 0000000..59606df --- /dev/null +++ b/xsacks.py @@ -0,0 +1,216 @@ +# How it works + +def cipher(message, key, skey): + message = str(message) + key = str(key) + skey = str(skey) + # Needed lists + messageCIPHER = [] + messageCIPHERAscii = [] + keyCIPHER = [] + keyCIPHERAscii = [] + messageASCII = [] + keyASCII = [] + keyASCII1 = [] + keyASCII2 = [] + skeyASCII = [] + + # Divide string in two parts (avoiding generating more than two parts) + keyPARTS = [] + n = int(len(key) / 2) + partnumber = 0 + for i in range(0, len(key), n): + partnumber += 1 + if not partnumber > 2: + keyPARTS.append(key[i: i + n]) + else: + keyPARTS[1] = keyPARTS[1] + key[i: i + n] + + # Convert everything in ascii + for char in message: + messageASCII.append(ord(char)) + for char in keyPARTS[0]: + keyASCII1.append(ord(char)) + for char in keyPARTS[1]: + keyASCII2.append(ord(char)) + for char in key: + keyASCII.append(ord(char)) + for char in skey: + skeyASCII.append(ord(char)) + + # Cipher + counterEven = 0 + counterOdd = 0 + for i in range(0, len(messageASCII)): + if (i % 2) == 0: + # Use the first part of the key + counterEven += 1 + if counterEven > len(keyASCII1) - 1: + counterEven = 0 + cipherResult = int(messageASCII[i]) + int(keyASCII1[counterEven]) + while (cipherResult > 125) or (cipherResult < 32): + if cipherResult > 125: + cipherResult = 31 + (cipherResult - 125) + if cipherResult < 32: + cipherResult = 126 - (32 - cipherResult) + messageCIPHER.append(cipherResult) + else: + # Use the second part of the key + counterOdd += 1 + if counterOdd > len(keyASCII2) - 1: + counterOdd = 0 + cipherResult = int(messageASCII[i]) + int(keyASCII2[counterOdd]) + while (cipherResult > 125) or (cipherResult < 32): + if cipherResult > 125: + cipherResult = 31 + (cipherResult - 125) + if cipherResult < 32: + cipherResult = 126 - (32 - cipherResult) + messageCIPHER.append(cipherResult) + + for char in messageCIPHER: + messageCIPHERAscii.append(chr(char)) + + # Cipher the key + counterSkey = 0 + for i in range(0, len(keyASCII)): + counterSkey += 1 + if counterSkey > len(skeyASCII) - 1: + counterSkey = 0 + cipherResult = int(keyASCII[i]) + int(skeyASCII[counterSkey]) + while (cipherResult > 125) or (cipherResult < 32): + if cipherResult > 125: + cipherResult = 31 + (cipherResult - 125) + if cipherResult < 32: + cipherResult = 126 - (32 - cipherResult) + keyCIPHER.append(cipherResult) + + for char in keyCIPHER: + keyCIPHERAscii.append(chr(char)) + + # Return a string + messageCIPHERstr = "" + for i in messageCIPHERAscii: + messageCIPHERstr = messageCIPHERstr + i + keyCIPHERstr = "" + for i in keyCIPHERAscii: + keyCIPHERstr = keyCIPHERstr + i + + return messageCIPHERstr, keyCIPHERstr + + +def decipher(message, key, securekey): + message = str(message) + key = str(key) + securekey = str(securekey) + # Needed lists + messageCIPHERAscii = [] + keyCIPHER = [] + skeyASCII = [] + keyDECIPHER = [] + keyDECIPHERChar = [] + keyDECIPHERParts = [] + keyDECIPHERParts1 = [] + keyDECIPHERParts2 = [] + messageDECIPHERAscii = [] + messageDECIPHERchar = [] + + # Convert everything in ascii + for char in message: + messageCIPHERAscii.append(ord(char)) + for char in key: + keyCIPHER.append(ord(char)) + for char in securekey: + skeyASCII.append(ord(char)) + + # Decipher the key + counterSkey = 0 + for i in range(0, len(keyCIPHER)): + counterSkey += 1 + if counterSkey > len(skeyASCII) - 1: + counterSkey = 0 + cipherResult = int(keyCIPHER[i]) - int(skeyASCII[counterSkey]) + while (cipherResult > 125) or (cipherResult < 32): + if cipherResult > 125: + cipherResult = 31 + (cipherResult - 125) + if cipherResult < 32: + cipherResult = 126 - (32 - cipherResult) + keyDECIPHER.append(cipherResult) + + for char in keyDECIPHER: + keyDECIPHERChar.append(chr(char)) + + # Divide the key deciphered + n = int(len(key) / 2) + partnumber = 0 + for i in range(0, len(keyDECIPHERChar), n): + partnumber += 1 + if not partnumber > 2: + keyDECIPHERParts.append(keyDECIPHERChar[i: i + n]) + else: + keyDECIPHERParts[1] = keyDECIPHERParts[1] + keyDECIPHERChar[i: i + n] + # Convert it to ascii + for char in keyDECIPHERParts[0]: + keyDECIPHERParts1.append(ord(char)) + for char in keyDECIPHERParts[1]: + keyDECIPHERParts2.append(ord(char)) + # Copy the functions to cipher but to decipher + counterEven = 0 + counterOdd = 0 + for i in range(0, len(messageCIPHERAscii)): + if (i % 2) == 0: + # Use the first part of the key + counterEven += 1 + if counterEven > len(keyDECIPHERParts1) - 1: + counterEven = 0 + cipherResult = int(messageCIPHERAscii[i]) - int(keyDECIPHERParts1[counterEven]) + while (cipherResult > 125) or (cipherResult < 32): + if cipherResult > 125: + cipherResult = 31 + (cipherResult - 125) + if cipherResult < 32: + cipherResult = 126 - (32 - cipherResult) + messageDECIPHERAscii.append(cipherResult) + else: + # Use the second part of the key + counterOdd += 1 + if counterOdd > len(keyDECIPHERParts2) - 1: + counterOdd = 0 + cipherResult = int(messageCIPHERAscii[i]) - int(keyDECIPHERParts2[counterOdd]) + while (cipherResult > 125) or (cipherResult < 32): + if cipherResult > 125: + cipherResult = 31 + (cipherResult - 125) + if cipherResult < 32: + cipherResult = 126 - (32 - cipherResult) + messageDECIPHERAscii.append(cipherResult) + + for char in messageDECIPHERAscii: + messageDECIPHERchar.append(chr(char)) + + # Return a string + messageDECIPHERAsciistr = "" + for i in messageDECIPHERchar: + messageDECIPHERAsciistr = messageDECIPHERAsciistr + i + keyDECIPHERstr = "" + for i in keyDECIPHERChar: + keyDECIPHERstr = keyDECIPHERstr + i + + return messageDECIPHERAsciistr, keyDECIPHERstr + + +if __name__ == "__main__": + message = "a simple message" + key = "casualkeytouse" + skey = "evenbetter" + + print("==TESTING MODE==") + print("=====") + print("Testing '" + message + "' encoded with '" + key + "' secured by '" + skey + "'") + print("=====") + messaggio_cifrato, chiave_cifrata = cipher(message, key, skey) + print(messaggio_cifrato) + print(chiave_cifrata) + print("=====") + print("Decoding '" + message + "' encoded with '" + key + "' secured by '" + skey + "'") + print("=====") + messaggio_decifrato, chiave_decifrata = decipher(messaggio_cifrato, chiave_cifrata, "evenbetter") + print(messaggio_decifrato) + print(chiave_decifrata)