mirror of
https://gitlab.com/MoonTestUse1/AdministrationItDepartmens.git
synced 2025-08-14 00:25:46 +02:00
Все подряд
This commit is contained in:
227
.venv2/Lib/site-packages/pyaes/blockfeeder.py
Normal file
227
.venv2/Lib/site-packages/pyaes/blockfeeder.py
Normal file
@@ -0,0 +1,227 @@
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2014 Richard Moore
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
from .aes import AESBlockModeOfOperation, AESSegmentModeOfOperation, AESStreamModeOfOperation
|
||||
from .util import append_PKCS7_padding, strip_PKCS7_padding, to_bufferable
|
||||
|
||||
|
||||
# First we inject three functions to each of the modes of operations
|
||||
#
|
||||
# _can_consume(size)
|
||||
# - Given a size, determine how many bytes could be consumed in
|
||||
# a single call to either the decrypt or encrypt method
|
||||
#
|
||||
# _final_encrypt(data, padding = PADDING_DEFAULT)
|
||||
# - call and return encrypt on this (last) chunk of data,
|
||||
# padding as necessary; this will always be at least 16
|
||||
# bytes unless the total incoming input was less than 16
|
||||
# bytes
|
||||
#
|
||||
# _final_decrypt(data, padding = PADDING_DEFAULT)
|
||||
# - same as _final_encrypt except for decrypt, for
|
||||
# stripping off padding
|
||||
#
|
||||
|
||||
PADDING_NONE = 'none'
|
||||
PADDING_DEFAULT = 'default'
|
||||
|
||||
# @TODO: Ciphertext stealing and explicit PKCS#7
|
||||
# PADDING_CIPHERTEXT_STEALING
|
||||
# PADDING_PKCS7
|
||||
|
||||
# ECB and CBC are block-only ciphers
|
||||
|
||||
def _block_can_consume(self, size):
|
||||
if size >= 16: return 16
|
||||
return 0
|
||||
|
||||
# After padding, we may have more than one block
|
||||
def _block_final_encrypt(self, data, padding = PADDING_DEFAULT):
|
||||
if padding == PADDING_DEFAULT:
|
||||
data = append_PKCS7_padding(data)
|
||||
|
||||
elif padding == PADDING_NONE:
|
||||
if len(data) != 16:
|
||||
raise Exception('invalid data length for final block')
|
||||
else:
|
||||
raise Exception('invalid padding option')
|
||||
|
||||
if len(data) == 32:
|
||||
return self.encrypt(data[:16]) + self.encrypt(data[16:])
|
||||
|
||||
return self.encrypt(data)
|
||||
|
||||
|
||||
def _block_final_decrypt(self, data, padding = PADDING_DEFAULT):
|
||||
if padding == PADDING_DEFAULT:
|
||||
return strip_PKCS7_padding(self.decrypt(data))
|
||||
|
||||
if padding == PADDING_NONE:
|
||||
if len(data) != 16:
|
||||
raise Exception('invalid data length for final block')
|
||||
return self.decrypt(data)
|
||||
|
||||
raise Exception('invalid padding option')
|
||||
|
||||
AESBlockModeOfOperation._can_consume = _block_can_consume
|
||||
AESBlockModeOfOperation._final_encrypt = _block_final_encrypt
|
||||
AESBlockModeOfOperation._final_decrypt = _block_final_decrypt
|
||||
|
||||
|
||||
|
||||
# CFB is a segment cipher
|
||||
|
||||
def _segment_can_consume(self, size):
|
||||
return self.segment_bytes * int(size // self.segment_bytes)
|
||||
|
||||
# CFB can handle a non-segment-sized block at the end using the remaining cipherblock
|
||||
def _segment_final_encrypt(self, data, padding = PADDING_DEFAULT):
|
||||
if padding != PADDING_DEFAULT:
|
||||
raise Exception('invalid padding option')
|
||||
|
||||
faux_padding = (chr(0) * (self.segment_bytes - (len(data) % self.segment_bytes)))
|
||||
padded = data + to_bufferable(faux_padding)
|
||||
return self.encrypt(padded)[:len(data)]
|
||||
|
||||
# CFB can handle a non-segment-sized block at the end using the remaining cipherblock
|
||||
def _segment_final_decrypt(self, data, padding = PADDING_DEFAULT):
|
||||
if padding != PADDING_DEFAULT:
|
||||
raise Exception('invalid padding option')
|
||||
|
||||
faux_padding = (chr(0) * (self.segment_bytes - (len(data) % self.segment_bytes)))
|
||||
padded = data + to_bufferable(faux_padding)
|
||||
return self.decrypt(padded)[:len(data)]
|
||||
|
||||
AESSegmentModeOfOperation._can_consume = _segment_can_consume
|
||||
AESSegmentModeOfOperation._final_encrypt = _segment_final_encrypt
|
||||
AESSegmentModeOfOperation._final_decrypt = _segment_final_decrypt
|
||||
|
||||
|
||||
|
||||
# OFB and CTR are stream ciphers
|
||||
|
||||
def _stream_can_consume(self, size):
|
||||
return size
|
||||
|
||||
def _stream_final_encrypt(self, data, padding = PADDING_DEFAULT):
|
||||
if padding not in [PADDING_NONE, PADDING_DEFAULT]:
|
||||
raise Exception('invalid padding option')
|
||||
|
||||
return self.encrypt(data)
|
||||
|
||||
def _stream_final_decrypt(self, data, padding = PADDING_DEFAULT):
|
||||
if padding not in [PADDING_NONE, PADDING_DEFAULT]:
|
||||
raise Exception('invalid padding option')
|
||||
|
||||
return self.decrypt(data)
|
||||
|
||||
AESStreamModeOfOperation._can_consume = _stream_can_consume
|
||||
AESStreamModeOfOperation._final_encrypt = _stream_final_encrypt
|
||||
AESStreamModeOfOperation._final_decrypt = _stream_final_decrypt
|
||||
|
||||
|
||||
|
||||
class BlockFeeder(object):
|
||||
'''The super-class for objects to handle chunking a stream of bytes
|
||||
into the appropriate block size for the underlying mode of operation
|
||||
and applying (or stripping) padding, as necessary.'''
|
||||
|
||||
def __init__(self, mode, feed, final, padding = PADDING_DEFAULT):
|
||||
self._mode = mode
|
||||
self._feed = feed
|
||||
self._final = final
|
||||
self._buffer = to_bufferable("")
|
||||
self._padding = padding
|
||||
|
||||
def feed(self, data = None):
|
||||
'''Provide bytes to encrypt (or decrypt), returning any bytes
|
||||
possible from this or any previous calls to feed.
|
||||
|
||||
Call with None or an empty string to flush the mode of
|
||||
operation and return any final bytes; no further calls to
|
||||
feed may be made.'''
|
||||
|
||||
if self._buffer is None:
|
||||
raise ValueError('already finished feeder')
|
||||
|
||||
# Finalize; process the spare bytes we were keeping
|
||||
if data is None:
|
||||
result = self._final(self._buffer, self._padding)
|
||||
self._buffer = None
|
||||
return result
|
||||
|
||||
self._buffer += to_bufferable(data)
|
||||
|
||||
# We keep 16 bytes around so we can determine padding
|
||||
result = to_bufferable('')
|
||||
while len(self._buffer) > 16:
|
||||
can_consume = self._mode._can_consume(len(self._buffer) - 16)
|
||||
if can_consume == 0: break
|
||||
result += self._feed(self._buffer[:can_consume])
|
||||
self._buffer = self._buffer[can_consume:]
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class Encrypter(BlockFeeder):
|
||||
'Accepts bytes of plaintext and returns encrypted ciphertext.'
|
||||
|
||||
def __init__(self, mode, padding = PADDING_DEFAULT):
|
||||
BlockFeeder.__init__(self, mode, mode.encrypt, mode._final_encrypt, padding)
|
||||
|
||||
|
||||
class Decrypter(BlockFeeder):
|
||||
'Accepts bytes of ciphertext and returns decrypted plaintext.'
|
||||
|
||||
def __init__(self, mode, padding = PADDING_DEFAULT):
|
||||
BlockFeeder.__init__(self, mode, mode.decrypt, mode._final_decrypt, padding)
|
||||
|
||||
|
||||
# 8kb blocks
|
||||
BLOCK_SIZE = (1 << 13)
|
||||
|
||||
def _feed_stream(feeder, in_stream, out_stream, block_size = BLOCK_SIZE):
|
||||
'Uses feeder to read and convert from in_stream and write to out_stream.'
|
||||
|
||||
while True:
|
||||
chunk = in_stream.read(block_size)
|
||||
if not chunk:
|
||||
break
|
||||
converted = feeder.feed(chunk)
|
||||
out_stream.write(converted)
|
||||
converted = feeder.feed()
|
||||
out_stream.write(converted)
|
||||
|
||||
|
||||
def encrypt_stream(mode, in_stream, out_stream, block_size = BLOCK_SIZE, padding = PADDING_DEFAULT):
|
||||
'Encrypts a stream of bytes from in_stream to out_stream using mode.'
|
||||
|
||||
encrypter = Encrypter(mode, padding = padding)
|
||||
_feed_stream(encrypter, in_stream, out_stream, block_size)
|
||||
|
||||
|
||||
def decrypt_stream(mode, in_stream, out_stream, block_size = BLOCK_SIZE, padding = PADDING_DEFAULT):
|
||||
'Decrypts a stream of bytes from in_stream to out_stream using mode.'
|
||||
|
||||
decrypter = Decrypter(mode, padding = padding)
|
||||
_feed_stream(decrypter, in_stream, out_stream, block_size)
|
Reference in New Issue
Block a user