Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added crypto class and cypher suites #1722

Closed
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
775ad35
added crypto class and cypher suites
sebmichel1983 Nov 22, 2020
cee1f88
added changelog entries
sebmichel1983 Nov 22, 2020
6568bc3
changed key sanitization request
sebmichel1983 Nov 22, 2020
bed84e1
fixed typo in vignere cipher
sebmichel1983 Nov 22, 2020
66bfeb0
fixed typo in vigenere
sebmichel1983 Nov 22, 2020
a371a6b
Removed 2.7
lukas-mertens Nov 22, 2020
6f33f39
Merge pull request #1 from lukas-mertens/dev
sebmichel1983 Nov 22, 2020
b49a08b
Addded 2.7 back in
lukas-mertens Nov 22, 2020
ba80385
Fixed lint
lukas-mertens Nov 22, 2020
c44a9d0
Added init
lukas-mertens Nov 22, 2020
40dae62
Removed self
lukas-mertens Nov 22, 2020
be96050
Reverted self
lukas-mertens Nov 22, 2020
b891849
changed code_table name
sebmichel1983 Nov 22, 2020
b30c82c
Code_table fix
lukas-mertens Nov 22, 2020
3edd060
Merge branch 'dev' of https://github.com/sebmichel1983/pwntools into dev
sebmichel1983 Nov 22, 2020
6a7cb55
Merge branch 'dev' into dev
lukas-mertens Nov 22, 2020
47a3b0f
Merge pull request #2 from lukas-mertens/dev
sebmichel1983 Nov 22, 2020
5b2acda
renamed cypher classes
sebmichel1983 Nov 25, 2020
415376f
Merge branch 'dev' of https://github.com/sebmichel1983/pwntools into dev
sebmichel1983 Nov 25, 2020
e2df120
renamed cipher classes
sebmichel1983 Nov 25, 2020
7c2fe96
changed type check to isinstance in vignere cipher
sebmichel1983 Nov 25, 2020
9526faf
changed class names to cipher_classname
sebmichel1983 Nov 25, 2020
3a91799
renamed crypto class in init
sebmichel1983 Nov 25, 2020
1f2a31b
normalized naming convention
sebmichel1983 Nov 25, 2020
b3c71af
fixed typo in vigenere cipher
sebmichel1983 Nov 25, 2020
c824825
changed if conditions to PEP8 standard
sebmichel1983 Nov 26, 2020
17e3ca3
test
procrash Dec 15, 2020
4be7c6f
cleanup
procrash Dec 15, 2020
1d3e5b5
Update
procrash Dec 15, 2020
febf259
Changed init.py
procrash Dec 15, 2020
789a710
added test.py to pwnlib folder
sebmichel1983 Dec 15, 2020
1de0165
moved test file
sebmichel1983 Dec 15, 2020
69d45ca
Not working
procrash Dec 15, 2020
7a42efd
changed CHANGELOG.md and index.rst in docs
sebmichel1983 Dec 15, 2020
5b09060
Latest changes
procrash Dec 15, 2020
f5710f9
Merge branch 'dev' of https://github.com/sebmichel1983/pwntools into dev
procrash Dec 15, 2020
ee5e32a
added more cipher suites and _notes.md
sebmichel1983 Dec 15, 2020
fa14ff0
Merge branch 'dev' into dev
Arusekk Apr 19, 2022
eb5579b
Merge branch 'dev' into dev
peace-maker Jun 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ The table below shows which release corresponds to each branch, and what date th
| [3.0.0](#300) | | Aug 20, 2016
| [2.2.0](#220) | | Jan 5, 2015

## 4.5.0 (`dev`)

## 4.5.0 (`dev`)
- [#1722][1722] Added Crypto class and cypher suites
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please try to keep these sorted. not change the blank lines formatting, and add a link as the other entries have below

- [#1261][1261] Misc `run_in_new_terminal` improvements (notably gdb terminated by default)
- [#1695][1695] Allow using GDB Python API

Expand Down
1 change: 1 addition & 0 deletions pwnlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
'asm',
'atexception',
'atexit',
'crypto',
'commandline',
'constants',
'context',
Expand Down
62 changes: 62 additions & 0 deletions pwnlib/crypto/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from __future__ import absolute_import

# load cipher suites
from pwnlib.crypto.ciphers.atbash import CipherAtBash
from pwnlib.crypto.ciphers.bacon import CipherBacon
from pwnlib.crypto.ciphers.base64 import CipherBase64
from pwnlib.crypto.ciphers.binary import CipherBinary
from pwnlib.crypto.ciphers.caesar import CipherCaesar
from pwnlib.crypto.ciphers.decimal import CipherDecimal
from pwnlib.crypto.ciphers.hex import CipherHex
from pwnlib.crypto.ciphers.morse import CipherMorse
from pwnlib.crypto.ciphers.reverse import CipherReverse
from pwnlib.crypto.ciphers.rot13 import CipherRot13
from pwnlib.crypto.ciphers.transposition import CipherTransposition
from pwnlib.crypto.ciphers.vigenere import CipherVigenere
from pwnlib.crypto.ciphers.xor import CipherXor

class Crypto():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to use the module hack seen elsewhere in Pwntools to make this "automagic"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im not sure what you mean with this, can you give me an example?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please also tell me, how to follow your suggestions about making routines top-level as you told here:

Edit: It would also be nice if all of these routines were exposed as top-level routines, e.g. crypto.rot13 rather than CryptoRot13. By convention, pretty much everything in Pwntools is lower-case.

I could rename the classes, but im not sure how to do this the way you want it to, that it fits.

def __init__(self, algo=None, key=None):
cipher = None
algo = algo
key = key

# select cipher suite
if(algo == 'atbash'):
Arusekk marked this conversation as resolved.
Show resolved Hide resolved
self.cipher = CipherAtBash()
if(algo == 'bacon'):
self.cipher = CipherBacon()
if(algo == 'base64'):
self.cipher = CipherBase64()
if(algo == 'binary'):
self.cipher = CipherBinary()
''' check key, mode parameter
if(algo == 'caesar'):
self.cipher = CipherCaesar()
if(algo == 'decimal'):
self.cipher = CipherDecimal()
'''
if(algo == 'hex'):
self.cipher = CipherHex()
if(algo == 'morse'):
self.cipher = CipherMorse()
if(algo == 'reverse'):
self.cipher = CipherReverse()
if(algo == 'rot13'):
self.cipher = CipherRot13()
'''
if(algo == 'transposition'):
self.cipher = CipherTransposition()
'''
if(algo == 'vignere'):
self.cipher = CipherVigenere()
if(algo == 'xor'):
self.cipher = CipherXor()


def encrypt(self, data):
return self.cipher.encrypt(data)


def decrypt(self, data):
return self.cipher.decrypt(data)
Empty file.
29 changes: 29 additions & 0 deletions pwnlib/crypto/ciphers/atbash.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import string

class CipherAtBash:
def __init__(self):
self.alphabet = list(string.ascii_uppercase)


def encrypt(self, clear):
return self.process(clear)


def decrypt(self, cipher):
return self.process(cipher)


def process(self, text):
reverse_alphabet = list(reversed(self.alphabet))
code_dictionary = dict(zip(self.alphabet, reverse_alphabet))

chars = list(text.upper())
result = ""

for char in chars:
if char in code_dictionary:
result += code_dictionary.get(char)
else:
result += char

return result
39 changes: 39 additions & 0 deletions pwnlib/crypto/ciphers/bacon.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import re

class CipherBacon:
def __init__(self):
self.code_table = self.generate_code_table()


def generate_code_table(self):
bacon_dict = {}

for i in range(0, 26):
tmp = bin(i)[2:].zfill(5)
tmp = tmp.replace('0', 'a')
tmp = tmp.replace('1', 'b')
bacon_dict[tmp] = chr(65 + i)

return bacon_dict


def encrypt(self, cleartext):
cipher = ''
bacon_dict = {v: k for k, v in self.code_table.items()} # hack to get key from value - reverse dict
#cleartext = normalize('NFKD', cleartext).encode('ascii', 'ignore') # replace national characters to ASCII equivalents
cleartext = cleartext.upper()
cleartext = re.sub(r'[^A-Z]+', '', cleartext)

for i in cleartext:
cipher += bacon_dict.get(i).upper()
return cipher


def decrypt(self, ciphertext):
cleartext = ''
ciphertext = ciphertext.lower()
ciphertext = re.sub(r'[^ab]+', '', ciphertext)

for i in range(0, int(len(ciphertext) / 5)):
cleartext += self.code_table.get(ciphertext[i * 5:i * 5 + 5], ' ')
return cleartext
9 changes: 9 additions & 0 deletions pwnlib/crypto/ciphers/base64.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import base64

class CipherBase64:
def encrypt(self, cleartext):
return base64.b64encode(cleartext.encode('utf-8')).decode()


def decrypt(self, ciphertext):
return base64.b64decode(ciphertext.encode('utf-8')).decode()
10 changes: 10 additions & 0 deletions pwnlib/crypto/ciphers/binary.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import binascii

class CipherBinary:
def encrypt(self, data):
return bin(int(binascii.hexlify(data.encode('utf-8')),16))


def decrypt(self, data):
n = int(data, 2)
return binascii.unhexlify('%x' % n).decode()
28 changes: 28 additions & 0 deletions pwnlib/crypto/ciphers/caesar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import string

class CipherCaesar:
def __init__(self):
self.alphabet = string.ascii_lowercase + string.ascii_uppercase


def encrypt(self, data, key, mode):
return self.process(data, key, mode)


def decrypt(self, data, key, mode):
return self.process(data, key, mode)


def process(self, text, key, mode):
result = ''

for c in text:
index = self.alphabet.find(c)
if index == -1:
result += c
else:
new_index = index + key if mode == 1 else index - key
new_index %= len(self.alphabet)
result += self.alphabet[new_index:new_index+1]

return result
19 changes: 19 additions & 0 deletions pwnlib/crypto/ciphers/decimal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import binascii

class CipherDecimal:
def encrypt(self, data):
result = ''

for char in data:
result += ord(char)

return result


def decrypt(self, data):
result = ''

for num in data:
result += chr(num)

return result
14 changes: 14 additions & 0 deletions pwnlib/crypto/ciphers/hex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import binascii

class CipherHex:
def encrypt(self, data):
result = ''

for char in data:
result += binascii.hexlify(char.encode('utf-8')).decode()

return result


def decrypt(self, data):
return binascii.unhexlify(data).decode()
55 changes: 55 additions & 0 deletions pwnlib/crypto/ciphers/morse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
class CipherMorse:
def __init__(self):
self.code_table = self.generate_code_table()


def generate_code_table(self):
code_table = {
'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':'--..',
'1':'.----', '2':'..---', '3':'...--',
'4':'....-', '5':'.....', '6':'-....',
'7':'--...', '8':'---..', '9':'----.',
'0':'-----', ', ':'--..--', '.':'.-.-.-',
'?':'..--..', '/':'-..-.', '-':'-....-',
'(':'-.--.', ')':'-.--.-'
}

return code_table


def encrypt(self, cleartext):
ciphertext = ''
for char in cleartext:
if char != ' ':
ciphertext += self.code_table[char.upper()] + ' '
else:
ciphertext += ' '

return ciphertext


def decrypt(self, ciphertext):
ciphertext += ' '
cleartext = ''
citext = ''
for char in ciphertext:
if (char != ' '):
i = 0
citext += char
else:
i += 1
if i == 2 :
cleartext += ' '
else:
cleartext += list(self.code_table.keys())[list(self.code_table.values()).index(citext)]
citext = ''

return cleartext
11 changes: 11 additions & 0 deletions pwnlib/crypto/ciphers/reverse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class CipherReverse:
def encrypt(self, cleartext):
return self.process(cleartext)


def decrypt(self, ciphertext):
return self.process(ciphertext)


def process(self, text):
return ''.join(reversed(text))
8 changes: 8 additions & 0 deletions pwnlib/crypto/ciphers/rot13.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import codecs

class CipherRot13:
def encrypt(self, data):
return codecs.encode(data, 'rot13')

def decrypt(self, data):
return codecs.decode(data, 'rot13')
43 changes: 43 additions & 0 deletions pwnlib/crypto/ciphers/transposition.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from __future__ import division
import math


class CipherTransposition:
def encrypt(self, data, key):
message_size = len(data)

if(key > message_size // 2):
raise ValueError('Key is limited to half the length of message')
else:
encrypted_message = [''] * key
for col in range(key):
pointer = col
while pointer < message_size:
encrypted_message[col] += data[pointer]
pointer += key

encrypted_message = ''.join(encrypted_message)
return encrypted_message


def decrypt(self, data, key):
num_of_columns = int(math.ceil(len(data) / key))
num_of_rows = key
num_of_shaded_boxes = (num_of_columns * num_of_rows) - len(data)

data = [''] * num_of_columns

col = 0
row = 0

for symbol in data:
data[col] += symbol
col += 1

if (col == num_of_columns or
col == num_of_columns - 1 and
row >= num_of_rows - num_of_shaded_boxes):
col = 0
row += 1

return ''.join(data)
Loading