initial commit

This commit is contained in:
2022-10-10 13:00:38 +02:00
commit 18ef4a0515
31 changed files with 2490 additions and 0 deletions

140
python/.gitignore vendored Normal file
View File

@@ -0,0 +1,140 @@
### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/

3
python/DES-20221006/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
pyDes.py.dec
pyDes.py.enc
*.pyc

View File

@@ -0,0 +1,45 @@
** 12th December 2011 **
Put on Github, use MIT license
** 28th April 2010 **
Release: 2.0.1
Fix triple des error when creating a CBC instance with no IV.
** 16th March 2009 **
Release: 2.0.0
Updated to work with Python3.
** 14th November 2008 **
Release: 1.3.1
Code: Patch by Shaya: fix PAD_PKCS5 padding modes when using triple des CBC.
Tests: Moved to separate test file.
** 28th October 2008 **
Release: 1.3
Code: Added PAD_NORMAL and PAD_PKCS5 padding modes.
Code: Implemented PKCS5 padding suport.
Code: Allow pad character and padmode to be set on a class instance.
** 23rd March 2007 **
License: Specified license as Public Domain everywhere.
** 12th September 2005 **
Release: 1.2
Code: Fixed errors with pyDes.triple_des() CBC mode.
Code: Added triple DES CBC checks to the testing procedures in __fulltest__()
** 7 May 2003 **
Code: pyDes.des and pyDes.triple_des now have an extra optional argument for
the encrypt and decrypt methods. This is for the padding character and
immediately follows the data field.
Code: Added error checking to the testing procedures in __fulltest__()
** 5 May 2003 **
Doc: Modified comments in Readme.txt and in pyDes.py header
Code: Changed Triple DES method to DES-EDE3 or DES-EDE2, depending on key size
Code: Optimized code by replacing inner for loops with map (now twice as fast)
Code: Changed all permutation tables to contain indexed locations instead of
byte offset locations
Code: Removed debugging line "Len of data: 1.0000"
Code: Included __filetest__() testing procedure

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 KiB

View File

@@ -0,0 +1,23 @@
Copyright (c) 2005-2012 Todd Whiteman. All rights reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,3 @@
include LICENSE.txt
include README.md
include pyDes.py

View File

@@ -0,0 +1,130 @@
# About
Author: Todd Whiteman
Version: 2.0.1
Release: 28th April, 2010
License: MIT
This is a pure python implementation of the DES encryption algorithm.
It's pure python to avoid portability issues, since most DES
implementations are programmed in C (for performance reasons).
## Installation
Using the Python package manager:
```bash
$ pip install pydes
```
### Or, for manual installation
Extract the files from the downloaded archive and run:
```
$ python setup.py install
```
If you'd like to run the tests, run the command:
```
$ python test_pydes.py
```
## Usage
```bash
python -c "import pyDes; des = pyDes.des('This Key'); \
print des.encrypt('SomeData').encode('hex')"
```
### Docs and Examples
```
Class initialization
--------------------
pyDes.des(key, [mode], [IV], [pad], [padmode])
pyDes.triple_des(key, [mode], [IV], [pad], [padmode])
key -> Bytes containing the encryption key. 8 bytes for DES, 16 or 24 bytes
for Triple DES
mode -> Optional argument for encryption type, can be either
pyDes.ECB (Electronic Code Book) or pyDes.CBC (Cypher Block Chaining)
IV -> Optional Initial Value bytes, must be supplied if using CBC mode.
Length must be 8 bytes.
pad -> Optional argument, set the pad character (PAD_NORMAL) to use during
all encrypt/decrpt operations done with this instance.
padmode -> Optional argument, set the padding mode (PAD_NORMAL or PAD_PKCS5)
to use during all encrypt/decrypt operations done with this instance.
I recommend to use PAD_PKCS5 padding, as then you never need to worry about any
padding issues, as the padding can be removed unambiguously upon decrypting
data that was encrypted using PAD_PKCS5 padmode.
Common methods
--------------
encrypt(data, [pad], [padmode])
decrypt(data, [pad], [padmode])
data -> Bytes to be encrypted/decrypted
pad -> Optional argument. Only when using padmode of PAD_NORMAL. For
encryption, adds this characters to the end of the data block when
data is not a multiple of 8 bytes. For decryption, will remove the
trailing characters that match this pad character from the last 8
bytes of the unencrypted data block.
padmode -> Optional argument, set the padding mode, must be one of PAD_NORMAL
or PAD_PKCS5). Defaults to PAD_NORMAL.
Example
-------
import pyDes
# For Python3, you'll need to use bytes, i.e.:
# data = b"Please encrypt my data"
# k = pyDes.des(b"DESCRYPT", pyDes.CBC, b"\0\0\0\0\0\0\0\0", pad=None, padmode=pyDes.PAD_PKCS5)
data = "Please encrypt my data"
k = pyDes.des("DESCRYPT", pyDes.CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=pyDes.PAD_PKCS5)
d = k.encrypt(data)
print "Encrypted: %r" % d
print "Decrypted: %r" % k.decrypt(d)
assert k.decrypt(d) == data
See the pyDes test file (test_pydes.py) for more examples of use.
Note: This code was not written for high-end systems needing a fast
implementation, but rather a handy portable solution with small usage.
```
## Performance
The code is not written for speed or performance, so not for those
needing a fast DES implementation, but rather a handy portable solution ideal
for small usages. The speed at which pyDes encrypts/decrypts is around 10Kb/s
(using the DES method) - that's very SLOW!!
## About triple DES
Triple DES is just running the DES algorithm 3 times over the data with the
specified key. The supplied key is split up into 3 parts, each part being 8
bytes long (the mandatory key size for DES).
The triple DES algorithm uses the DES-EDE3 method when a 24 byte key is
supplied. This means there are three DES operations in the sequence
encrypt-decrypt-encrypt with the three different keys. The first key will be
bytes 1 to 8, the second key bytes 9 to 16 and the third key bytes 17 to 24.
If a 16 byte key is supplied instead, the triple DES method used will be
DES-EDE2. This means there are three DES operations in the sequence
encrypt-decrypt-encrypt, but the first and third operations use the same key.
The first/third key will be bytes 1 to 8 and the second key bytes 9 to 16.
## Credits
Thanks go to:
- David Broadwell: Ideas, comments and suggestions.
- Mario Wolff: Finding and debugging triple des CBC errors.
- Santiago Palladino: Providing the PKCS5 padding technique.
- Shaya: Fixing triple DES CBC errors with PAD_PKCS5.
- Yoav Aner: For spotting a triple DES CBC IV error.

View File

@@ -0,0 +1,852 @@
#############################################################################
# Documentation #
#############################################################################
# Author: Todd Whiteman
# Date: 28th April, 2010
# Version: 2.0.1
# License: MIT
# Homepage: http://twhiteman.netfirms.com/des.html
#
# This is a pure python implementation of the DES encryption algorithm.
# It's pure python to avoid portability issues, since most DES
# implementations are programmed in C (for performance reasons).
#
# Triple DES class is also implemented, utilizing the DES base. Triple DES
# is either DES-EDE3 with a 24 byte key, or DES-EDE2 with a 16 byte key.
#
# See the README.txt that should come with this python module for the
# implementation methods used.
#
# Thanks to:
# * David Broadwell for ideas, comments and suggestions.
# * Mario Wolff for pointing out and debugging some triple des CBC errors.
# * Santiago Palladino for providing the PKCS5 padding technique.
# * Shaya for correcting the PAD_PKCS5 triple des CBC errors.
#
"""A pure python implementation of the DES and TRIPLE DES encryption algorithms.
Class initialization
--------------------
pyDes.des(key, [mode], [IV], [pad], [padmode])
pyDes.triple_des(key, [mode], [IV], [pad], [padmode])
key -> Bytes containing the encryption key. 8 bytes for DES, 16 or 24 bytes
for Triple DES
mode -> Optional argument for encryption type, can be either
pyDes.ECB (Electronic Code Book) or pyDes.CBC (Cypher Block Chaining)
IV -> Optional Initial Value bytes, must be supplied if using CBC mode.
Length must be 8 bytes.
pad -> Optional argument, set the pad character (PAD_NORMAL) to use during
all encrypt/decrypt operations done with this instance.
padmode -> Optional argument, set the padding mode (PAD_NORMAL or PAD_PKCS5)
to use during all encrypt/decrypt operations done with this instance.
I recommend to use PAD_PKCS5 padding, as then you never need to worry about any
padding issues, as the padding can be removed unambiguously upon decrypting
data that was encrypted using PAD_PKCS5 padmode.
Common methods
--------------
encrypt(data, [pad], [padmode])
decrypt(data, [pad], [padmode])
data -> Bytes to be encrypted/decrypted
pad -> Optional argument. Only when using padmode of PAD_NORMAL. For
encryption, adds this characters to the end of the data block when
data is not a multiple of 8 bytes. For decryption, will remove the
trailing characters that match this pad character from the last 8
bytes of the unencrypted data block.
padmode -> Optional argument, set the padding mode, must be one of PAD_NORMAL
or PAD_PKCS5). Defaults to PAD_NORMAL.
Example
-------
from pyDes import *
data = "Please encrypt my data"
k = des("DESCRYPT", CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)
# For Python3, you'll need to use bytes, i.e.:
# data = b"Please encrypt my data"
# k = des(b"DESCRYPT", CBC, b"\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)
d = k.encrypt(data)
print "Encrypted: %r" % d
print "Decrypted: %r" % k.decrypt(d)
assert k.decrypt(d, padmode=PAD_PKCS5) == data
See the module source (pyDes.py) for more examples of use.
You can also run the pyDes.py file without and arguments to see a simple test.
Note: This code was not written for high-end systems needing a fast
implementation, but rather a handy portable solution with small usage.
"""
import sys
# _pythonMajorVersion is used to handle Python2 and Python3 differences.
_pythonMajorVersion = sys.version_info[0]
# Modes of crypting / cyphering
ECB = 0
CBC = 1
# Modes of padding
PAD_NORMAL = 1
PAD_PKCS5 = 2
# PAD_PKCS5: is a method that will unambiguously remove all padding
# characters after decryption, when originally encrypted with
# this padding mode.
# For a good description of the PKCS5 padding technique, see:
# http://www.faqs.org/rfcs/rfc1423.html
# The base class shared by des and triple des.
class _baseDes(object):
def __init__(self, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL):
if IV:
IV = self._guardAgainstUnicode(IV)
if pad:
pad = self._guardAgainstUnicode(pad)
self.block_size = 8
# Sanity checking of arguments.
if pad and padmode == PAD_PKCS5:
raise ValueError("Cannot use a pad character with PAD_PKCS5")
if IV and len(IV) != self.block_size:
raise ValueError("Invalid Initial Value (IV), must be a multiple of " + str(self.block_size) + " bytes")
# Set the passed in variables
self._mode = mode
self._iv = IV
self._padding = pad
self._padmode = padmode
def getKey(self):
"""getKey() -> bytes"""
return self.__key
def setKey(self, key):
"""Will set the crypting key for this object."""
key = self._guardAgainstUnicode(key)
self.__key = key
def getMode(self):
"""getMode() -> pyDes.ECB or pyDes.CBC"""
return self._mode
def setMode(self, mode):
"""Sets the type of crypting mode, pyDes.ECB or pyDes.CBC"""
self._mode = mode
def getPadding(self):
"""getPadding() -> bytes of length 1. Padding character."""
return self._padding
def setPadding(self, pad):
"""setPadding() -> bytes of length 1. Padding character."""
if pad is not None:
pad = self._guardAgainstUnicode(pad)
self._padding = pad
def getPadMode(self):
"""getPadMode() -> pyDes.PAD_NORMAL or pyDes.PAD_PKCS5"""
return self._padmode
def setPadMode(self, mode):
"""Sets the type of padding mode, pyDes.PAD_NORMAL or pyDes.PAD_PKCS5"""
self._padmode = mode
def getIV(self):
"""getIV() -> bytes"""
return self._iv
def setIV(self, IV):
"""Will set the Initial Value, used in conjunction with CBC mode"""
if not IV or len(IV) != self.block_size:
raise ValueError("Invalid Initial Value (IV), must be a multiple of " + str(self.block_size) + " bytes")
IV = self._guardAgainstUnicode(IV)
self._iv = IV
def _padData(self, data, pad, padmode):
# Pad data depending on the mode
if padmode is None:
# Get the default padding mode.
padmode = self.getPadMode()
if pad and padmode == PAD_PKCS5:
raise ValueError("Cannot use a pad character with PAD_PKCS5")
if padmode == PAD_NORMAL:
if len(data) % self.block_size == 0:
# No padding required.
return data
if not pad:
# Get the default padding.
pad = self.getPadding()
if not pad:
raise ValueError("Data must be a multiple of " + str(self.block_size) + " bytes in length. Use padmode=PAD_PKCS5 or set the pad character.")
data += (self.block_size - (len(data) % self.block_size)) * pad
elif padmode == PAD_PKCS5:
pad_len = 8 - (len(data) % self.block_size)
if _pythonMajorVersion < 3:
data += pad_len * chr(pad_len)
else:
data += bytes([pad_len] * pad_len)
return data
def _unpadData(self, data, pad, padmode):
# Unpad data depending on the mode.
if not data:
return data
if pad and padmode == PAD_PKCS5:
raise ValueError("Cannot use a pad character with PAD_PKCS5")
if padmode is None:
# Get the default padding mode.
padmode = self.getPadMode()
if padmode == PAD_NORMAL:
if not pad:
# Get the default padding.
pad = self.getPadding()
if pad:
data = data[:-self.block_size] + \
data[-self.block_size:].rstrip(pad)
elif padmode == PAD_PKCS5:
if _pythonMajorVersion < 3:
pad_len = ord(data[-1])
else:
pad_len = data[-1]
data = data[:-pad_len]
return data
def _guardAgainstUnicode(self, data):
# Only accept byte strings or ascii unicode values, otherwise
# there is no way to correctly decode the data into bytes.
if _pythonMajorVersion < 3:
if isinstance(data, unicode):
raise ValueError("pyDes can only work with bytes, not Unicode strings.")
else:
if isinstance(data, str):
# Only accept ascii unicode values.
try:
return data.encode('ascii')
except UnicodeEncodeError:
pass
raise ValueError("pyDes can only work with encoded strings, not Unicode.")
return data
#############################################################################
# DES #
#############################################################################
class des(_baseDes):
"""DES encryption/decrytpion class
Supports ECB (Electronic Code Book) and CBC (Cypher Block Chaining) modes.
pyDes.des(key,[mode], [IV])
key -> Bytes containing the encryption key, must be exactly 8 bytes
mode -> Optional argument for encryption type, can be either pyDes.ECB
(Electronic Code Book), pyDes.CBC (Cypher Block Chaining)
IV -> Optional Initial Value bytes, must be supplied if using CBC mode.
Must be 8 bytes in length.
pad -> Optional argument, set the pad character (PAD_NORMAL) to use
during all encrypt/decrypt operations done with this instance.
padmode -> Optional argument, set the padding mode (PAD_NORMAL or
PAD_PKCS5) to use during all encrypt/decrypt operations done
with this instance.
"""
# Permutation and translation tables for DES
__pc1 = [56, 48, 40, 32, 24, 16, 8,
0, 57, 49, 41, 33, 25, 17,
9, 1, 58, 50, 42, 34, 26,
18, 10, 2, 59, 51, 43, 35,
62, 54, 46, 38, 30, 22, 14,
6, 61, 53, 45, 37, 29, 21,
13, 5, 60, 52, 44, 36, 28,
20, 12, 4, 27, 19, 11, 3
]
# number left rotations of pc1
__left_rotations = [
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
]
# permuted choice key (table 2)
__pc2 = [
13, 16, 10, 23, 0, 4,
2, 27, 14, 5, 20, 9,
22, 18, 11, 3, 25, 7,
15, 6, 26, 19, 12, 1,
40, 51, 30, 36, 46, 54,
29, 39, 50, 44, 32, 47,
43, 48, 38, 55, 33, 52,
45, 41, 49, 35, 28, 31
]
# initial permutation IP
__ip = [57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7,
56, 48, 40, 32, 24, 16, 8, 0,
58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6
]
# Expansion table for turning 32 bit blocks into 48 bits
__expansion_table = [
31, 0, 1, 2, 3, 4,
3, 4, 5, 6, 7, 8,
7, 8, 9, 10, 11, 12,
11, 12, 13, 14, 15, 16,
15, 16, 17, 18, 19, 20,
19, 20, 21, 22, 23, 24,
23, 24, 25, 26, 27, 28,
27, 28, 29, 30, 31, 0
]
# The (in)famous S-boxes
__sbox = [
# S1
[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13],
# S2
[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9],
# S3
[10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12],
# S4
[7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14],
# S5
[2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3],
# S6
[12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13],
# S7
[4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12],
# S8
[13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11],
]
# 32-bit permutation function P used on the output of the S-boxes
__p = [
15, 6, 19, 20, 28, 11,
27, 16, 0, 14, 22, 25,
4, 17, 30, 9, 1, 7,
23,13, 31, 26, 2, 8,
18, 12, 29, 5, 21, 10,
3, 24
]
# final permutation IP^-1
__fp = [
39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30,
37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25,
32, 0, 40, 8, 48, 16, 56, 24
]
# Type of crypting being done
ENCRYPT = 0x00
DECRYPT = 0x01
# Initialisation
def __init__(self, key, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL):
# Sanity checking of arguments.
if len(key) != 8:
raise ValueError("Invalid DES key size. Key must be exactly 8 bytes long.")
_baseDes.__init__(self, mode, IV, pad, padmode)
self.key_size = 8
self.L = []
self.R = []
self.Kn = [ [0] * 48 ] * 16 # 16 48-bit keys (K1 - K16)
self.final = []
self.setKey(key)
def setKey(self, key):
"""Will set the crypting key for this object. Must be 8 bytes."""
_baseDes.setKey(self, key)
self.__create_sub_keys()
def __String_to_BitList(self, data):
"""Turn the string data, into a list of bits (1, 0)'s"""
if _pythonMajorVersion < 3:
# Turn the strings into integers. Python 3 uses a bytes
# class, which already has this behaviour.
data = [ord(c) for c in data]
l = len(data) * 8
result = [0] * l
pos = 0
for ch in data:
i = 7
while i >= 0:
if ch & (1 << i) != 0:
result[pos] = 1
else:
result[pos] = 0
pos += 1
i -= 1
return result
def __BitList_to_String(self, data):
"""Turn the list of bits -> data, into a string"""
result = []
pos = 0
c = 0
while pos < len(data):
c += data[pos] << (7 - (pos % 8))
if (pos % 8) == 7:
result.append(c)
c = 0
pos += 1
if _pythonMajorVersion < 3:
return ''.join([ chr(c) for c in result ])
else:
return bytes(result)
def __permutate(self, table, block):
"""Permutate this block with the specified table"""
return list(map(lambda x: block[x], table))
# Transform the secret key, so that it is ready for data processing
# Create the 16 subkeys, K[1] - K[16]
def __create_sub_keys(self):
"""Create the 16 subkeys K[1] to K[16] from the given key"""
key = self.__permutate(des.__pc1, self.__String_to_BitList(self.getKey()))
i = 0
# Split into Left and Right sections
self.L = key[:28]
self.R = key[28:]
while i < 16:
j = 0
# Perform circular left shifts
while j < des.__left_rotations[i]:
self.L.append(self.L[0])
del self.L[0]
self.R.append(self.R[0])
del self.R[0]
j += 1
# Create one of the 16 subkeys through pc2 permutation
self.Kn[i] = self.__permutate(des.__pc2, self.L + self.R)
i += 1
# Main part of the encryption algorithm, the number cruncher :)
def __des_crypt(self, block, crypt_type):
"""Crypt the block of data through DES bit-manipulation"""
block = self.__permutate(des.__ip, block)
self.L = block[:32]
self.R = block[32:]
# Encryption starts from Kn[1] through to Kn[16]
if crypt_type == des.ENCRYPT:
iteration = 0
iteration_adjustment = 1
# Decryption starts from Kn[16] down to Kn[1]
else:
iteration = 15
iteration_adjustment = -1
i = 0
while i < 16:
# Make a copy of R[i-1], this will later become L[i]
tempR = self.R[:]
# Permutate R[i - 1] to start creating R[i]
self.R = self.__permutate(des.__expansion_table, self.R)
# Exclusive or R[i - 1] with K[i], create B[1] to B[8] whilst here
self.R = list(map(lambda x, y: x ^ y, self.R, self.Kn[iteration]))
B = [self.R[:6], self.R[6:12], self.R[12:18], self.R[18:24], self.R[24:30], self.R[30:36], self.R[36:42], self.R[42:]]
# Optimization: Replaced below commented code with above
#j = 0
#B = []
#while j < len(self.R):
# self.R[j] = self.R[j] ^ self.Kn[iteration][j]
# j += 1
# if j % 6 == 0:
# B.append(self.R[j-6:j])
# Permutate B[1] to B[8] using the S-Boxes
j = 0
Bn = [0] * 32
pos = 0
while j < 8:
# Work out the offsets
m = (B[j][0] << 1) + B[j][5]
n = (B[j][1] << 3) + (B[j][2] << 2) + (B[j][3] << 1) + B[j][4]
# Find the permutation value
v = des.__sbox[j][(m << 4) + n]
# Turn value into bits, add it to result: Bn
Bn[pos] = (v & 8) >> 3
Bn[pos + 1] = (v & 4) >> 2
Bn[pos + 2] = (v & 2) >> 1
Bn[pos + 3] = v & 1
pos += 4
j += 1
# Permutate the concatination of B[1] to B[8] (Bn)
self.R = self.__permutate(des.__p, Bn)
# Xor with L[i - 1]
self.R = list(map(lambda x, y: x ^ y, self.R, self.L))
# Optimization: This now replaces the below commented code
#j = 0
#while j < len(self.R):
# self.R[j] = self.R[j] ^ self.L[j]
# j += 1
# L[i] becomes R[i - 1]
self.L = tempR
i += 1
iteration += iteration_adjustment
# Final permutation of R[16]L[16]
self.final = self.__permutate(des.__fp, self.R + self.L)
return self.final
# Data to be encrypted/decrypted
def crypt(self, data, crypt_type):
"""Crypt the data in blocks, running it through des_crypt()"""
# Error check the data
if not data:
return ''
if len(data) % self.block_size != 0:
if crypt_type == des.DECRYPT: # Decryption must work on 8 byte blocks
raise ValueError("Invalid data length, data must be a multiple of " + str(self.block_size) + " bytes\n.")
if not self.getPadding():
raise ValueError("Invalid data length, data must be a multiple of " + str(self.block_size) + " bytes\n. Try setting the optional padding character")
else:
data += (self.block_size - (len(data) % self.block_size)) * self.getPadding()
# print "Len of data: %f" % (len(data) / self.block_size)
if self.getMode() == CBC:
if self.getIV():
iv = self.__String_to_BitList(self.getIV())
else:
raise ValueError("For CBC mode, you must supply the Initial Value (IV) for ciphering")
# Split the data into blocks, crypting each one seperately
i = 0
dict = {}
result = []
#cached = 0
#lines = 0
while i < len(data):
# Test code for caching encryption results
#lines += 1
#if dict.has_key(data[i:i+8]):
#print "Cached result for: %s" % data[i:i+8]
# cached += 1
# result.append(dict[data[i:i+8]])
# i += 8
# continue
block = self.__String_to_BitList(data[i:i+8])
# Xor with IV if using CBC mode
if self.getMode() == CBC:
if crypt_type == des.ENCRYPT:
block = list(map(lambda x, y: x ^ y, block, iv))
#j = 0
#while j < len(block):
# block[j] = block[j] ^ iv[j]
# j += 1
processed_block = self.__des_crypt(block, crypt_type)
if crypt_type == des.DECRYPT:
processed_block = list(map(lambda x, y: x ^ y, processed_block, iv))
#j = 0
#while j < len(processed_block):
# processed_block[j] = processed_block[j] ^ iv[j]
# j += 1
iv = block
else:
iv = processed_block
else:
processed_block = self.__des_crypt(block, crypt_type)
# Add the resulting crypted block to our list
#d = self.__BitList_to_String(processed_block)
#result.append(d)
result.append(self.__BitList_to_String(processed_block))
#dict[data[i:i+8]] = d
i += 8
# print "Lines: %d, cached: %d" % (lines, cached)
# Return the full crypted string
if _pythonMajorVersion < 3:
return ''.join(result)
else:
return bytes.fromhex('').join(result)
def encrypt(self, data, pad=None, padmode=None):
"""encrypt(data, [pad], [padmode]) -> bytes
data : Bytes to be encrypted
pad : Optional argument for encryption padding. Must only be one byte
padmode : Optional argument for overriding the padding mode.
The data must be a multiple of 8 bytes and will be encrypted
with the already specified key. Data does not have to be a
multiple of 8 bytes if the padding character is supplied, or
the padmode is set to PAD_PKCS5, as bytes will then added to
ensure the be padded data is a multiple of 8 bytes.
"""
data = self._guardAgainstUnicode(data)
if pad is not None:
pad = self._guardAgainstUnicode(pad)
data = self._padData(data, pad, padmode)
return self.crypt(data, des.ENCRYPT)
def decrypt(self, data, pad=None, padmode=None):
"""decrypt(data, [pad], [padmode]) -> bytes
data : Bytes to be decrypted
pad : Optional argument for decryption padding. Must only be one byte
padmode : Optional argument for overriding the padding mode.
The data must be a multiple of 8 bytes and will be decrypted
with the already specified key. In PAD_NORMAL mode, if the
optional padding character is supplied, then the un-encrypted
data will have the padding characters removed from the end of
the bytes. This pad removal only occurs on the last 8 bytes of
the data (last data block). In PAD_PKCS5 mode, the special
padding end markers will be removed from the data after decrypting.
"""
data = self._guardAgainstUnicode(data)
if pad is not None:
pad = self._guardAgainstUnicode(pad)
data = self.crypt(data, des.DECRYPT)
return self._unpadData(data, pad, padmode)
#############################################################################
# Triple DES #
#############################################################################
class triple_des(_baseDes):
"""Triple DES encryption/decrytpion class
This algorithm uses the DES-EDE3 (when a 24 byte key is supplied) or
the DES-EDE2 (when a 16 byte key is supplied) encryption methods.
Supports ECB (Electronic Code Book) and CBC (Cypher Block Chaining) modes.
pyDes.des(key, [mode], [IV])
key -> Bytes containing the encryption key, must be either 16 or
24 bytes long
mode -> Optional argument for encryption type, can be either pyDes.ECB
(Electronic Code Book), pyDes.CBC (Cypher Block Chaining)
IV -> Optional Initial Value bytes, must be supplied if using CBC mode.
Must be 8 bytes in length.
pad -> Optional argument, set the pad character (PAD_NORMAL) to use
during all encrypt/decrypt operations done with this instance.
padmode -> Optional argument, set the padding mode (PAD_NORMAL or
PAD_PKCS5) to use during all encrypt/decrypt operations done
with this instance.
"""
def __init__(self, key, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL):
_baseDes.__init__(self, mode, IV, pad, padmode)
self.setKey(key)
def setKey(self, key):
"""Will set the crypting key for this object. Either 16 or 24 bytes long."""
self.key_size = 24 # Use DES-EDE3 mode
if len(key) != self.key_size:
if len(key) == 16: # Use DES-EDE2 mode
self.key_size = 16
else:
raise ValueError("Invalid triple DES key size. Key must be either 16 or 24 bytes long")
if self.getMode() == CBC:
if not self.getIV():
# Use the first 8 bytes of the key
self._iv = key[:self.block_size]
if len(self.getIV()) != self.block_size:
raise ValueError("Invalid IV, must be 8 bytes in length")
self.__key1 = des(key[:8], self._mode, self._iv,
self._padding, self._padmode)
self.__key2 = des(key[8:16], self._mode, self._iv,
self._padding, self._padmode)
if self.key_size == 16:
self.__key3 = self.__key1
else:
self.__key3 = des(key[16:], self._mode, self._iv,
self._padding, self._padmode)
_baseDes.setKey(self, key)
# Override setter methods to work on all 3 keys.
def setMode(self, mode):
"""Sets the type of crypting mode, pyDes.ECB or pyDes.CBC"""
_baseDes.setMode(self, mode)
for key in (self.__key1, self.__key2, self.__key3):
key.setMode(mode)
def setPadding(self, pad):
"""setPadding() -> bytes of length 1. Padding character."""
_baseDes.setPadding(self, pad)
for key in (self.__key1, self.__key2, self.__key3):
key.setPadding(pad)
def setPadMode(self, mode):
"""Sets the type of padding mode, pyDes.PAD_NORMAL or pyDes.PAD_PKCS5"""
_baseDes.setPadMode(self, mode)
for key in (self.__key1, self.__key2, self.__key3):
key.setPadMode(mode)
def setIV(self, IV):
"""Will set the Initial Value, used in conjunction with CBC mode"""
_baseDes.setIV(self, IV)
for key in (self.__key1, self.__key2, self.__key3):
key.setIV(IV)
def encrypt(self, data, pad=None, padmode=None):
"""encrypt(data, [pad], [padmode]) -> bytes
data : bytes to be encrypted
pad : Optional argument for encryption padding. Must only be one byte
padmode : Optional argument for overriding the padding mode.
The data must be a multiple of 8 bytes and will be encrypted
with the already specified key. Data does not have to be a
multiple of 8 bytes if the padding character is supplied, or
the padmode is set to PAD_PKCS5, as bytes will then added to
ensure the be padded data is a multiple of 8 bytes.
"""
ENCRYPT = des.ENCRYPT
DECRYPT = des.DECRYPT
data = self._guardAgainstUnicode(data)
if pad is not None:
pad = self._guardAgainstUnicode(pad)
# Pad the data accordingly.
data = self._padData(data, pad, padmode)
if self.getMode() == CBC:
self.__key1.setIV(self.getIV())
self.__key2.setIV(self.getIV())
self.__key3.setIV(self.getIV())
i = 0
result = []
while i < len(data):
block = self.__key1.crypt(data[i:i+8], ENCRYPT)
block = self.__key2.crypt(block, DECRYPT)
block = self.__key3.crypt(block, ENCRYPT)
self.__key1.setIV(block)
self.__key2.setIV(block)
self.__key3.setIV(block)
result.append(block)
i += 8
if _pythonMajorVersion < 3:
return ''.join(result)
else:
return bytes.fromhex('').join(result)
else:
data = self.__key1.crypt(data, ENCRYPT)
data = self.__key2.crypt(data, DECRYPT)
return self.__key3.crypt(data, ENCRYPT)
def decrypt(self, data, pad=None, padmode=None):
"""decrypt(data, [pad], [padmode]) -> bytes
data : bytes to be encrypted
pad : Optional argument for decryption padding. Must only be one byte
padmode : Optional argument for overriding the padding mode.
The data must be a multiple of 8 bytes and will be decrypted
with the already specified key. In PAD_NORMAL mode, if the
optional padding character is supplied, then the un-encrypted
data will have the padding characters removed from the end of
the bytes. This pad removal only occurs on the last 8 bytes of
the data (last data block). In PAD_PKCS5 mode, the special
padding end markers will be removed from the data after
decrypting, no pad character is required for PAD_PKCS5.
"""
ENCRYPT = des.ENCRYPT
DECRYPT = des.DECRYPT
data = self._guardAgainstUnicode(data)
if pad is not None:
pad = self._guardAgainstUnicode(pad)
if self.getMode() == CBC:
self.__key1.setIV(self.getIV())
self.__key2.setIV(self.getIV())
self.__key3.setIV(self.getIV())
i = 0
result = []
while i < len(data):
iv = data[i:i+8]
block = self.__key3.crypt(iv, DECRYPT)
block = self.__key2.crypt(block, ENCRYPT)
block = self.__key1.crypt(block, DECRYPT)
self.__key1.setIV(iv)
self.__key2.setIV(iv)
self.__key3.setIV(iv)
result.append(block)
i += 8
if _pythonMajorVersion < 3:
data = ''.join(result)
else:
data = bytes.fromhex('').join(result)
else:
data = self.__key3.crypt(data, DECRYPT)
data = self.__key2.crypt(data, ENCRYPT)
data = self.__key1.crypt(data, DECRYPT)
return self._unpadData(data, pad, padmode)

View File

@@ -0,0 +1,5 @@
[bdist_wheel]
# This flag says that the code is written to work on both Python 2 and Python
# 3. If at all possible, it is good practice to do this. If you cannot, you
# will need to generate wheels for each Python version that you support.
universal=1

View File

@@ -0,0 +1,23 @@
#!/usr/bin/env python
from distutils.core import setup
setup(name="pyDes",
version="2.0.1",
description="Pure python implementation of DES and TRIPLE DES encryption algorithm",
author="Todd Whiteman",
author_email="twhitema@gmail.com",
license='MIT',
url="http://twhiteman.netfirms.com/des.html",
classifiers=[
'Development Status :: 6 - Mature'
'License :: OSI Approved :: MIT License',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 3',
'Topic :: Security :: Cryptography',
],
platforms=["All"],
keywords=["DES", "TRIPLE-DES", "ENCRYPTION", "ALGORITHM", "SECURITY"],
py_modules=["pyDes"]
)

View File

@@ -0,0 +1,24 @@
from pyDes import *
from binascii import unhexlify as unhex
if __name__ == '__main__':
f = open("Image1.bmp", "rb")
head = f.read(62)
image = f.read()
f.close()
k1 = des(unhex("133457799BBCDFF1"), ECB, padmode=PAD_PKCS5)
k2 = des(unhex("133457799BBCDFF1"), CBC, IV=b'01110010', padmode=PAD_PKCS5)
e1 = k1.encrypt(image)
e2 = k2.encrypt(image)
with open("Image2.bmp", "wb") as f:
f.write(head)
f.write(e1)
with open("Image3.bmp", "wb") as f:
f.write(head)
f.write(e2)
# d1 = k1.decrypt(e1)

View File

@@ -0,0 +1,259 @@
from pyDes import *
#############################################################################
# Examples #
#############################################################################
def _example_triple_des_():
from time import time
# Utility module
from binascii import unhexlify as unhex
# example shows triple-des encryption using the des class
print ("Example of triple DES encryption in default ECB mode (DES-EDE3)\n")
print ("Triple des using the des class (3 times)")
t = time()
k1 = des(unhex("133457799BBCDFF1"))
k2 = des(unhex("1122334455667788"))
k3 = des(unhex("77661100DD223311"))
d = "Triple DES test string, to be encrypted and decrypted..."
print ("Key1: %r" % k1.getKey())
print ("Key2: %r" % k2.getKey())
print ("Key3: %r" % k3.getKey())
print ("Data: %r" % d)
e1 = k1.encrypt(d)
e2 = k2.decrypt(e1)
e3 = k3.encrypt(e2)
print ("Encrypted: %r" % e3)
d3 = k3.decrypt(e3)
d2 = k2.encrypt(d3)
d1 = k1.decrypt(d2)
print ("Decrypted: %r" % d1)
print ("DES time taken: %f (%d crypt operations)" % (time() - t, 6 * (len(d) / 8)))
print ("")
# Example below uses the triple-des class to achieve the same as above
print ("Now using triple des class")
t = time()
t1 = triple_des(unhex("133457799BBCDFF1112233445566778877661100DD223311"))
print ("Key: %r" % t1.getKey())
print ("Data: %r" % d)
td1 = t1.encrypt(d)
print ("Encrypted: %r" % td1)
td2 = t1.decrypt(td1)
print ("Decrypted: %r" % td2)
print ("Triple DES time taken: %f (%d crypt operations)" % (time() - t, 6 * (len(d) / 8)))
def _example_des_():
from time import time
# example of DES encrypting in CBC mode with the IV of "\0\0\0\0\0\0\0\0"
print ("Example of DES encryption using CBC mode\n")
t = time()
k = des("DESCRYPT", CBC, "\0\0\0\0\0\0\0\0")
data = "DES encryption algorithm"
print ("Key : %r" % k.getKey())
print ("Data : %r" % data)
d = k.encrypt(data)
print ("Encrypted: %r" % d)
d = k.decrypt(d)
print ("Decrypted: %r" % d)
print ("DES time taken: %f (6 crypt operations)" % (time() - t))
print ("")
def _filetest_():
from time import time
f = open("pyDes.py", "rb+")
d = f.read()
f.close()
t = time()
k = des("MyDESKey")
d = k.encrypt(d, " ")
f = open("pyDes.py.enc", "wb+")
f.write(d)
f.close()
d = k.decrypt(d, " ")
f = open("pyDes.py.dec", "wb+")
f.write(d)
f.close()
print ("DES file test time: %f" % (time() - t))
def _profile_():
try:
import cProfile as profile
except:
import profile
profile.run('_fulltest_()')
#profile.run('_filetest_()')
def _fulltest_():
# This should not produce any unexpected errors or exceptions
from time import time
from binascii import unhexlify as unhex
from binascii import hexlify as dohex
t = time()
data = "DES encryption algorithm".encode('ascii')
k = des("\0\0\0\0\0\0\0\0", CBC, "\0\0\0\0\0\0\0\0")
d = k.encrypt(data)
if k.decrypt(d) != data:
print ("Test 1: Error: decrypt does not match. %r != %r" % (data, k.decrypt(d)))
else:
print ("Test 1: Successful")
data = "Default string of text".encode('ascii')
k = des("\0\0\0\0\0\0\0\0", CBC, "\0\0\0\0\0\0\0\0")
d = k.encrypt(data, "*")
if k.decrypt(d, "*") != data:
print ("Test 2: Error: decrypt does not match. %r != %r" % (data, k.decrypt(d)))
else:
print ("Test 2: Successful")
data = "String to Pad".encode('ascii')
k = des("\r\n\tABC\r\n")
d = k.encrypt(data, "*")
if k.decrypt(d, "*") != data:
print ("Test 3: Error: decrypt does not match. %r != %r" % (data, k.decrypt(d)))
else:
print ("Test 3: Successful")
k = des("\r\n\tABC\r\n")
d = k.encrypt(unhex("000102030405060708FF8FDCB04080"), unhex("44"))
if k.decrypt(d, unhex("44")) != unhex("000102030405060708FF8FDCB04080"):
print ("Test 4a: Error: Unencypted data block does not match start data")
elif k.decrypt(d) != unhex("000102030405060708FF8FDCB0408044"):
print ("Test 4b: Error: Unencypted data block does not match start data")
else:
print ("Test 4: Successful")
data = "String to Pad".encode('ascii')
k = des("\r\n\tkey\r\n")
d = k.encrypt(data, padmode=PAD_PKCS5)
if k.decrypt(d, padmode=PAD_PKCS5) != data:
print ("Test 5a: Error: decrypt does not match. %r != %r" % (data, k.decrypt(d)))
# Try same with padmode set on the class instance.
k = des("\r\n\tkey\r\n", padmode=PAD_PKCS5)
d = k.encrypt(data)
if k.decrypt(d) != data:
print ("Test 5b: Error: decrypt does not match. %r != %r" % (data, k.decrypt(d)))
else:
print ("Test 5: Successful")
k = triple_des("MyDesKey\r\n\tABC\r\n0987*543")
d = k.encrypt(unhex("000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080"))
if k.decrypt(d) != unhex("000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080"):
print ("Test 6: Error: Unencypted data block does not match start data")
else:
print ("Test 6: Successful")
k = triple_des("\r\n\tABC\r\n0987*543")
d = k.encrypt(unhex("000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080"))
if k.decrypt(d) != unhex("000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080"):
print ("Test 7: Error: Unencypted data block does not match start data")
else:
print ("Test 7: Successful")
k = triple_des("MyDesKey\r\n\tABC\r\n0987*54B", CBC, "12341234")
d = k.encrypt(unhex("000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080"))
if k.decrypt(d) != unhex("000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080"):
print ("Test 8: Error: Triple DES CBC failed.")
else:
print ("Test 8: Successful")
k = triple_des("MyDesKey\r\n\tABC\r\n0987*54B", CBC, "12341234")
d = k.encrypt(unhex("000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDC"), '.')
if k.decrypt(d, '.') != unhex("000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDCB04080000102030405060708FF8FDC"):
print ("Test 9: Error: Triple DES CBC with padding failed.")
else:
print ("Test 9: Successful")
k = triple_des("\r\n\tkey\rIsGoodKey")
data = "String to Pad".encode('ascii')
d = k.encrypt(data, padmode=PAD_PKCS5)
if k.decrypt(d, padmode=PAD_PKCS5) != data:
print ("Test 10: Error: decrypt does not match. %r != %r" % (data, k.decrypt(d)))
else:
print ("Test 10: Successful")
k = triple_des("\r\n\tkey\rIsGoodKey")
data = "String not need Padding.".encode('ascii')
d = k.encrypt(data, padmode=PAD_PKCS5)
if k.decrypt(d, padmode=PAD_PKCS5) != data:
print ("Test 11: Error: decrypt does not match. %r != %r" % (data, k.decrypt(d)))
else:
print ("Test 11: Successful")
# Test PAD_PKCS5 with CBC encryption mode.
k = des("IGoodKey", mode=CBC, IV="\0\1\2\3\4\5\6\7")
data = "String to Pad".encode('ascii')
d = k.encrypt(data, padmode=PAD_PKCS5)
if k.decrypt(d, padmode=PAD_PKCS5) != data:
print ("Test 12: Error: decrypt does not match. %r != %r" % (data, k.decrypt(d)))
else:
print ("Test 12: Successful")
k = des("IGoodKey", mode=CBC, IV="\0\1\2\3\4\5\6\7")
data = "String not need Padding.".encode('ascii')
d = k.encrypt(data, padmode=PAD_PKCS5)
if k.decrypt(d, padmode=PAD_PKCS5) != data:
print ("Test 13: Error: decrypt does not match. %r != %r" % (data, k.decrypt(d)))
else:
print ("Test 13: Successful")
k = triple_des("\r\n\tkey\rIsGoodKey", mode=CBC, IV="\0\1\2\3\4\5\6\7")
data = "String to Pad".encode('ascii')
d = k.encrypt(data, padmode=PAD_PKCS5)
if k.decrypt(d, padmode=PAD_PKCS5) != data:
print ("Test 14: Error: decrypt does not match. %r != %r" % (data, k.decrypt(d)))
else:
print ("Test 14: Successful")
k = triple_des("\r\n\tkey\rIsGoodKey", mode=CBC, IV="\0\1\2\3\4\5\6\7")
data = "String not need Padding.".encode('ascii')
d = k.encrypt(data, padmode=PAD_PKCS5)
if k.decrypt(d, padmode=PAD_PKCS5) != data:
print ("Test 15: Error: decrypt does not match. %r != %r" % (data, k.decrypt(d)))
else:
print ("Test 15: Successful")
k = triple_des("\r\n\tkey\rIsGoodKey", mode=CBC, IV="\0\1\2\3\4\5\6\7", padmode=PAD_PKCS5)
data = "String to Pad".encode('ascii')
d = k.encrypt(data)
if k.decrypt(d) != data:
print ("Test 16: Error: decrypt does not match. %r != %r" % (data, k.decrypt(d)))
else:
print ("Test 16: Successful")
# Ensure no error occurs when creating an instance with no IV yet set,
# test supplied by "Yoav Aner".
k = triple_des("\0" * 24, mode=CBC, pad=None, padmode=PAD_PKCS5)
data = "String to Pad".encode('ascii')
d = k.encrypt(data)
if k.decrypt(d) != data:
print ("Test 17: Error: decrypt does not match. %r != %r" % (data, k.decrypt(d)))
else:
print ("Test 17: Successful")
print ("")
print ("Total time taken: %f" % (time() - t))
if __name__ == '__main__':
#_example_des_()
#_example_triple_des_()
_fulltest_()
#_filetest_()
#_profile_()

View File

@@ -0,0 +1,37 @@
DES
Plaintext: 02468aceeca86420
Key: 0f1571c947d9e859
Ciphertext: da02ce3a89ecac3b
Change the 4th bit in the plaintext
Plaintext: 12468aceeca86420
Key: 0f1571c947d9e859
Ciphertext: 057cde97d7683f2a => 38e8c912b2bf81ef
Change the 4th bit in the key
Plaintext: 02468aceeca86420
Key: 1f1571c947d9e859
Ciphertext: ee92b50606b62b0b => eae5cedbb5fd55f8
Weak keys
AES
Plaintext: 0123456789abcdeffedcba9876543210
Key: 0f1571c947d9e8590cb7add6af7f6798
Ciphertext:
Change of the 8th bit in the plaintext
Plaintext: 0023456789abcdeffedcba9876543210
Key: 0f1571c947d9e8590cb7add6af7f6798
Ciphertext:
Change of the 8th bit in the key
Plaintext: 0123456789abcdeffedcba9876543210
Key: 0e1571c947d9e8590cb7add6af7f6798
Ciphertext:

47
python/des/README.md Normal file
View File

@@ -0,0 +1,47 @@
pydes
=====
Basic but pure DES implementation in Python
I have written it for fun because nothing else.
How it works ?
--------------
Everything is made within a class called "des". This class can be instanciated once and used to cipher and decipher multiple datas.
It also support padding using the PKCS5 specification. (So the data is padding even if it is multiple of 8 to be sure that the last byte il be padding data).
The generation of all the keys used is made in the method generatekeys and substitute apply the SBOX permutation.
The main method is run which is called by both encrypt and decrypt but in a different mode. This method do basically all the stuff, it loop
throught all the blocks and for each do the 16th rounds.
Be careful: This module implement DES in ECB mode, so you can't make it weaker. I didn't made it to be strong but for fun.
How to use it ?
---------------
I have not done any interface to take argument in command line so this module can't be used as a script. (feel free to modify it).
To use it from python shell or in another module do:
from pydes import des
key = "secret_k"
text= "Hello wo"
d = des()
ciphered = d.encrypt(key,text)
plain = d.decrypt(key,ciphered)
print "Ciphered: %r" % ciphered
print "Deciphered: ", plain
Note: In this exemple no padding is specified so you have to provide a text which is multiple of 8 bytes. The key is cut to 8 bytes if longer.
To use padding:
from pydes import des
key = "secret_k"
text= "Hello world !"
d = des()
ciphered = d.encrypt(key,text,padding=True) #Or just True in third arg
plain = d.decrypt(key,ciphered,padding=True)
print "Ciphered: %r" % ciphered
print "Deciphered: ", plain

270
python/des/pydes.py Normal file
View File

@@ -0,0 +1,270 @@
# -*- coding: utf8 -*-
import binascii
# Initial permut matrix for the datas
PI = [58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7]
# Initial permut made on the key
CP_1 = [57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4]
# Permut applied on shifted key to get Ki+1
CP_2 = [14, 17, 11, 24, 1, 5, 3, 28,
15, 6, 21, 10, 23, 19, 12, 4,
26, 8, 16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55, 30, 40,
51, 45, 33, 48, 44, 49, 39, 56,
34, 53, 46, 42, 50, 36, 29, 32]
# Expand matrix to get a 48bits matrix of datas to apply the xor with Ki
E = [32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13,
12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21,
20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29,
28, 29, 30, 31, 32, 1]
# SBOX
S_BOX = [
[[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7],
[0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8],
[4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0],
[15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13],
],
[[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10],
[3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5],
[0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15],
[13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9],
],
[[10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8],
[13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1],
[13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7],
[1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12],
],
[[7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15],
[13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9],
[10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4],
[3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14],
],
[[2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9],
[14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6],
[4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14],
[11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3],
],
[[12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11],
[10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8],
[9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6],
[4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13],
],
[[4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1],
[13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6],
[1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2],
[6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12],
],
[[13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7],
[1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2],
[7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8],
[2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11],
]
]
# Permut made after each SBox substitution for each round
P = [16, 7, 20, 21, 29, 12, 28, 17,
1, 15, 23, 26, 5, 18, 31, 10,
2, 8, 24, 14, 32, 27, 3, 9,
19, 13, 30, 6, 22, 11, 4, 25]
# Final permut for datas after the 16 rounds
PI_1 = [40, 8, 48, 16, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30,
37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25]
# Matrix that determine the shift for each round of keys
SHIFT = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]
def string_to_bit_array(text): # Convert a string into a list of bits
array = list()
for char in text:
binval = binvalue(char, 8) # Get the char value on one byte
array.extend([int(x) for x in list(binval)]) # Add the bits to the final list
return array
def bit_array_to_string(array): # Recreate the string from the bit array
res = ''.join([chr(int(y, 2)) for y in [''.join([str(x) for x in bytes]) for bytes in nsplit(array, 8)]])
return res
def binvalue(val, bitsize): # Return the binary value as a string of the given size
binval = bin(val)[2:] if isinstance(val, int) else bin(ord(val))[2:]
if len(binval) > bitsize:
raise "binary value larger than the expected size"
while len(binval) < bitsize:
binval = "0" + binval # Add as many 0 as needed to get the wanted size
return binval
def nsplit(s, n): # Split a list into sublists of size "n"
return [s[k:k + n] for k in range(0, len(s), n)]
ENCRYPT = 1
DECRYPT = 0
class des():
def __init__(self):
self.password = None
self.text = None
self.keys = list()
def run(self, key, text, action=ENCRYPT, padding=False):
if len(key) < 8:
raise "Key Should be 8 bytes long"
elif len(key) > 8:
key = key[:8] # If key size is above 8bytes, cut to be 8bytes long
self.password = key
self.text = text
if padding and action == ENCRYPT:
self.addPadding()
elif len(self.text) % 8 != 0: # If not padding specified data size must be multiple of 8 bytes
raise "Data size should be multiple of 8"
self.generatekeys() # Generate all the keys
text_blocks = nsplit(self.text, 8) # Split the text in blocks of 8 bytes so 64 bits
result = list()
for block in text_blocks: # Loop over all the blocks of data
block = string_to_bit_array(block) # Convert the block in bit array
block = self.permut(block, PI) # Apply the initial permutation
g, d = nsplit(block, 32) # g(LEFT), d(RIGHT)
tmp = None
for i in range(16): # Do the 16 rounds
d_e = self.expand(d, E) # Expand d to match Ki size (48bits)
if action == ENCRYPT:
tmp = self.xor(self.keys[i], d_e) # If encrypt use Ki
else:
tmp = self.xor(self.keys[15 - i], d_e) # If decrypt start by the last key
tmp = self.substitute(tmp) # Method that will apply the SBOXes
tmp = self.permut(tmp, P)
tmp = self.xor(g, tmp)
g = d
d = tmp
print(g, end="")
print(d)
print(hex(int("".join(str(x) for x in g+d), 2)))
result += self.permut(d + g, PI_1) # Do the last permut and append the result to result
print(" -------- ")
print("Result : ",result)
print(hex(int("".join(str(x) for x in result), 2)))
print()
final_res = bit_array_to_string(result)
if padding and action == DECRYPT:
return self.removePadding(final_res) # Remove the padding if decrypt and padding is true
else:
return final_res # Return the final string of data ciphered/deciphered
def substitute(self, d_e): # Substitute bytes using SBOX
subblocks = nsplit(d_e, 6) # Split bit array into sublist of 6 bits
result = list()
for i in range(len(subblocks)): # For all the sublists
block = subblocks[i]
row = int(str(block[0]) + str(block[5]), 2) # Get the row with the first and last bit
column = int(''.join([str(x) for x in block[1:][:-1]]), 2) # Column is the 2,3,4,5th bits
val = S_BOX[i][row][column] # Take the value in the SBOX appropriated for the round (i)
bin = binvalue(val, 4) # Convert the value to binary
result += [int(x) for x in bin] # And append it to the resulting list
return result
def permut(self, block, table): # Permut the given block using the given table (so generic method)
return [block[x - 1] for x in table]
def expand(self, block, table): # Do the exact same thing than permut but for more clarity has been renamed
return [block[x - 1] for x in table]
def xor(self, t1, t2): # Apply a xor and return the resulting list
return [x ^ y for x, y in zip(t1, t2)]
def generatekeys(self): # Algorithm that generates all the keys
self.keys = []
key = string_to_bit_array(self.password)
key = self.permut(key, CP_1) # Apply the initial permut on the key
g, d = nsplit(key, 28) # Split it in to (g->LEFT),(d->RIGHT)
for i in range(16): # Apply the 16 rounds
g, d = self.shift(g, d, SHIFT[i]) # Apply the shift associated with the round (not always 1)
tmp = g + d # Merge them
self.keys.append(self.permut(tmp, CP_2)) # Apply the permut to get the Ki
def shift(self, g, d, n): # Shift a list of the given value
return g[n:] + g[:n], d[n:] + d[:n]
def addPadding(self): # Add padding to the datas using PKCS5 spec.
pad_len = 8 - (len(self.text) % 8)
self.text += pad_len * chr(pad_len)
def removePadding(self, data): # Remove the padding of the plain text (it assume there is padding)
pad_len = ord(data[-1])
return data[:-pad_len]
def encrypt(self, key, text, padding=False):
return self.run(key, text, ENCRYPT, padding)
def decrypt(self, key, text, padding=False):
return self.run(key, text, DECRYPT, padding)
def flip(txt, pos):
if len(text) > pos:
if txt[pos] == 1:
txt[pos] = 0
else:
txt[pos] = 1
if __name__ == '__main__':
key_hex = b'02468aceeca86420'
key = binascii.unhexlify(key_hex)
text_hex = b'0f1571c947d9e859'
text = binascii.unhexlify(text_hex)
print(text)
d = des()
r = d.encrypt(key, text)
r2 = d.decrypt(key, r)
print("Ciphered: %r" % r)
print("Ciphered: %r" % binascii.hexlify(r.encode('latin1')))
print("Deciphered: %r" % r2)
print("Deciphered: %r" % binascii.hexlify(r2.encode('latin1')))

View File

@@ -0,0 +1,268 @@
# -*- coding: utf-8 -*-
"""
Created on Sun Nov 3 15:30:59 2019
This module converts string to hex, hex to string, ...
@author: Patrice MEGRET
"""
import binascii
def hex_to_string(h, show='y', coding='Latin-1'):
"""Conversion from hex to string.
Args:
h: hexa string
show: print conversion (default 'y')
coding: string coding (default 'Latin-1')
Returns:
h_s: string coded with coding
Internal:
h_by: h in byte
"""
h_by = binascii.unhexlify(h)
h_s = h_by.decode(coding)
if show == "y":
print("Hex = ", h, "Len = ", len(h))
print("Bytes = ", h_by, "Len = ", len(h_by))
print('{0} = {1}, Len = {2!r}'.format(coding, h_s, len(h_s)))
print('ASCII = {0!a}, Len = {1}'.format(h_s, len(h_s)))
print("\n")
return h_s
def hex_to_byte(h, show='y', coding='Latin-1'):
"""Conversion from hex to byte.
Args:
h: hexa string
show: print conversion (default 'y')
coding: string coding (default 'Latin-1')
Returns:
h_by: h in byte
"""
h_by = binascii.unhexlify(h)
if show == "y":
print("Hex = ", h, "Len = ", len(h))
print("Bytes = ", h_by, "Len = ", len(h_by))
print("\n")
return h_by
def string_to_hex(s, show="y", coding="Latin-1"):
"""Conversion from string to hex.
Args:
s: string
show: print conversion (default 'y')
coding: string coding (default 'Latin-1')
Returns:
s_h: string in hexa
Internal:
s_by: s in byte with coding
"""
s_by = s.encode(coding)
s_h = binascii.hexlify(s_by)
if show == "y":
print('ASCII = {0!a}, Len = {1}'.format(s, len(s)))
print('{0} = {1}, Len = {2!r}'.format(coding, s, len(s)))
print("Bytes = ", s_by, "Len = ", len(s_by))
print("Hex = ", s_h, "Len = ", len(s_h))
print("\n")
return s_h
def byte_to_hex(b, show="y", coding="Latin-1"):
"""Conversion from byte to hex.
Args:
b: bytes
show: print conversion (default 'y')
coding: string coding (default 'Latin-1')
Returns:
b_h: string in hexa
"""
b_h = binascii.hexlify(b)
if show == "y":
print("Bytes = ", b, "Len = ", len(b))
print("Hex = ", b_h, "Len = ", len(b_h))
print("\n")
return b_h
def hex_to_bin(h, show="y"):
"""Conversion from hex to bin.
Args:
h: hexa string
show: print conversion (default 'y')
Returns:
b: binary equivalent of h
"""
b = bin(int(h, 16)) # b is a string beginning with 0b
if show == "y":
print("Bin = ", b, "Len = ", len(b) - 2)
print('\n')
return b
def hex_to_bin_des(h, show="y"):
"""Conversion from hex to bin and display 64 bits.
Args:
h: hexa string
show: print conversion (default 'y')
Returns:
b: binary equivalent of h
"""
b = bin(int(h, 16)) # b is a string beginning with 0b
if show == "y":
print('Bin = {0:064b}'.format(int(h, 16)))
print('\n')
return b
def bin_to_hex(b, show="y"):
"""Conversion bin to hex.
Args:
b: binary string
show: print conversion (default 'y')
Returns:
h: hexa equivalent of h
"""
h = hex(int(b, 2)) # h is a string beginning with 0x
if show == "y":
print("Hex = ", h, "Len = ", len(h) - 2)
print('\n')
return h
def bin_to_hex_des(b, show="y"):
"""Conversion bin to hex and display 16 hexa.
Args:
b: binary string
show: print conversion (default 'y')
Returns:
h: hexa equivalent of h
"""
h = hex(int(b, 2)) # h is a string beginning with 0x
if show == "y":
print('Hex = {:016x}'.format(int(b, 2)))
print('\n')
return h
def xor_hex(h1_str, h2_str):
"""Xor between two hexa strings.
Args:
h1_str: hexa string 1
h2_str: hexa string 2
Returns:
print xor between the two hexa strings
"""
i1 = int(h1_str, 16)
i2 = int(h2_str, 16)
x = i1 ^ i2
xb_str = bin(x)
n1 = xb_str.count('1')
print(xb_str, n1)
print('\n')
def binvalue(val, bitsize):
"""Return the binary value as a string of a given size.
Args:
val: integer or one character
bitsize: number of bits for the conversion
Returns:
binval: string of bitsize-length
"""
# bin returns a string beginning with 0b ==> extract [2:] to cut these two characters
binval = bin(val)[2:] if isinstance(val, int) else bin(ord(val))[2:]
if len(binval) > bitsize:
raise "binary value larger than the expected size"
while len(binval) < bitsize:
binval = "0" + binval # Add as many 0 as needed to get the wanted size
return binval
def hexvalue(val, hexsize):
"""Return the hex value as a string of the given size.
Args:
val: integer or one character
hexsize: number of hex for the conversion
Returns:
hexval: string of hexsize-length
"""
# hex returns a string beginning with 0x ==> extract [2:] to cut these two characters
hexval = hex(val)[2:] if isinstance(val, int) else hex(ord(val))[2:]
if len(hexval) > hexsize:
raise "hex value larger than the expected size"
while len(hexval) < hexsize:
hexval = "0" + hexval # Add as many 0 as needed to get the wanted size
return hexval
def string_to_hex_array(text):
"""Convert a string into a list of hex.
Args:
text: string
Returns:
array: array of hexvalues
"""
array = list()
for char in text:
hexval = hexvalue(char, 2) # Get the char value on two hex
array.extend([x for x in list(hexval)]) # Add the hex to the final list
return array
def hex_array_to_string(array):
"""Recreate the string from the hex array.
Args:
array: array of hex
Returns:
res: string
"""
res = ''.join([chr(int(y, 16)) for y in [''.join([str(x) for x in hexa]) for hexa in nsplit(array, 2)]])
return res
def bit_array_to_hex(array, bitgroup, hexsize):
"""Return the hex value from an array of bits.
Args:
array: array of bits
bitgroup: number of bits to be grpoupo for the conversion
hexsize: number of hex for the conversion of bitgroup bits
Returns:
res: string of hex
"""
res = ''.join(
[hexvalue(int(y, 2), hexsize) for y in [''.join([str(x) for x in hexa]) for hexa in nsplit(array, bitgroup)]])
return res
def nsplit(s, n): # Split a list into sublists of size "n"
return [s[k:k + n] for k in range(0, len(s), n)]
if __name__ == '__main__':
hs = b'370FFF'
hex_to_string(hs)
ss = 'test é'
string_to_hex(ss)
hex_to_bin('FF')
bin_to_hex('1111')
xor_hex('FF', '11')

81
python/freq/main.py Normal file
View File

@@ -0,0 +1,81 @@
txt = "NTCGPDOPANFLHJINTOOFITOVJHJCTMMHIHEMTCPFDWTSOFSHTOGFWTETTJJTBTOOFSZOVEOCHCVCHPJHOCGTOHNQMTOCNTCGPDCGFCSTQMFBTOFBGFSFBCTSHJCGTQMFHJCTYCXHCGFAHYTDDHAATSTJCBGFSFBCTSHJCGTBHQGTSCTYCCGHONTCGPDQSTOTSWTOCGTMTCCTSASTRVTJBZHJCGTQMFHJCTYCFJDOPPJTBFJOTFSBGAPSCGTQMFHJCTYCASPNFIHWTJBHQGTSCTYCEZBPNQFSHJICGTASTRVTJBZPATFBGMTCCTSFIFHJOCCGTLJPXJBPNNPJASTRVTJBZHJCGTVJDTSMZHJIMFJIVFIT"
freq_tab = ["E", "T", "A", "I", "N", "O", "S", "R", "L", "D", "H", "C", "U", "M", "F", "P", "Y", "G", "W", "V", "B",
"K", "X", "J", "Q", "Z"]
def freq_letter(txt):
dic = {}
for letter in txt:
if letter in dic:
dic[letter] += 1
else:
dic[letter] = 1
return dict(sorted(dic.items(), key=lambda item: item[1]))
def freq_m_letter(txt, nbr=2):
dic = {}
i = 0
while i < len(txt) - 1:
letter = txt[i:i + nbr]
if letter in dic:
dic[letter] += 1
else:
dic[letter] = 1
i += 1
return dict(sorted(filter(lambda x: x[1] > 2, dic.items()), key=lambda item: item[1]))
def trad(txt_, replace_):
sol = ""
for letter in txt_:
if letter in replace_:
sol += replace_[letter]
else:
sol += letter
return sol
if __name__ == '__main__':
replace = {"C": "t",
"G": "h",
"T": "e",
"H": "i",
"J": "n",
"S": "r",
"F": "a",
"Y": "x",
"B": "c",
"I": "g",
"M": "l",
"Q": "p",
"V": "u",
"A": "f",
"R": "q",
"Z": "y",
"D": "d",
"P": "o",
"O": "s",
"N": "m",
"L": "k",
"E": "b",
"W": "v",
"X": "w"
}
freq = freq_letter(txt)
print(freq)
for i in range(2, 10):
print("===")
freq_2 = freq_m_letter(txt, i)
print(freq_2)
print('{', end=" ")
for a in freq_2:
print(trad(a, replace), end=', ')
print('}')
sol = trad(txt, replace)
print('====')
print(sol)

36
python/prime/prime.py Normal file
View File

@@ -0,0 +1,36 @@
def factor_decomposition(n):
p = 2
dec = {}
# print(n,"= ",end="")
while n >= p * p:
if n % p == 0:
if p in dec:
dec[p] += 1
else:
dec[p] = 1
# print(p, "* ", end="")
n /= p
else:
p += 1
# print(n)
if n in dec:
dec[n] += 1
else:
dec[n] = 1
return dec
def phi(n):
sol = 1
dec = factor_decomposition(n)
for (p, a) in dec.items():
sol *= (p**(a-1))*(p-1)
return sol
if __name__ == '__main__':
print(factor_decomposition(85))
print(factor_decomposition(1200))
print(factor_decomposition(11011))
print(phi(9))
print(phi(85))

11
python/python.iml Normal file
View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/venv" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>