initial commit
This commit is contained in:
140
python/.gitignore
vendored
Normal file
140
python/.gitignore
vendored
Normal 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
3
python/DES-20221006/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
pyDes.py.dec
|
||||
pyDes.py.enc
|
||||
*.pyc
|
||||
45
python/DES-20221006/Changelog.txt
Normal file
45
python/DES-20221006/Changelog.txt
Normal 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
|
||||
BIN
python/DES-20221006/Image1.bmp
Normal file
BIN
python/DES-20221006/Image1.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 411 KiB |
BIN
python/DES-20221006/Image2.bmp
Normal file
BIN
python/DES-20221006/Image2.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 411 KiB |
BIN
python/DES-20221006/Image3.bmp
Normal file
BIN
python/DES-20221006/Image3.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 411 KiB |
23
python/DES-20221006/LICENSE.txt
Normal file
23
python/DES-20221006/LICENSE.txt
Normal 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.
|
||||
|
||||
3
python/DES-20221006/MANIFEST.in
Normal file
3
python/DES-20221006/MANIFEST.in
Normal file
@@ -0,0 +1,3 @@
|
||||
include LICENSE.txt
|
||||
include README.md
|
||||
include pyDes.py
|
||||
130
python/DES-20221006/README.md
Normal file
130
python/DES-20221006/README.md
Normal 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.
|
||||
852
python/DES-20221006/pyDes.py
Normal file
852
python/DES-20221006/pyDes.py
Normal 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)
|
||||
5
python/DES-20221006/setup.cfg
Normal file
5
python/DES-20221006/setup.cfg
Normal 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
|
||||
23
python/DES-20221006/setup.py
Normal file
23
python/DES-20221006/setup.py
Normal 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"]
|
||||
)
|
||||
24
python/DES-20221006/test.py
Normal file
24
python/DES-20221006/test.py
Normal 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)
|
||||
259
python/DES-20221006/test_pydes.py
Normal file
259
python/DES-20221006/test_pydes.py
Normal 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_()
|
||||
37
python/des/DES-AES_test..txt
Normal file
37
python/des/DES-AES_test..txt
Normal 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
47
python/des/README.md
Normal 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
270
python/des/pydes.py
Normal 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')))
|
||||
268
python/des/string_conversion_tools.py
Normal file
268
python/des/string_conversion_tools.py
Normal 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
81
python/freq/main.py
Normal 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
36
python/prime/prime.py
Normal 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
11
python/python.iml
Normal 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>
|
||||
Reference in New Issue
Block a user