spluspy 2.0.7__tar.gz → 2.0.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {spluspy-2.0.7 → spluspy-2.0.8}/CHANGELOG.md +3 -2
- {spluspy-2.0.7 → spluspy-2.0.8}/PKG-INFO +1 -1
- {spluspy-2.0.7 → spluspy-2.0.8}/pyproject.toml +1 -1
- spluspy-2.0.8/setup.py +48 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/__version__.py +1 -1
- spluspy-2.0.8/spluspy/_engine/crypto/__init__.py +86 -0
- spluspy-2.0.8/spluspy/_engine/crypto/fast_aes.pyx +226 -0
- spluspy-2.0.8/spluspy/_engine/crypto/fast_rsa.pyx +312 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/extensions/binaryreader.py +29 -3
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/mtprotosender.py +1 -1
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/client/client.py +227 -18
- spluspy-2.0.7/spluspy/_engine/crypto/__init__.py +0 -10
- {spluspy-2.0.7 → spluspy-2.0.8}/.gitignore +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/CONTRIBUTING.md +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/Dockerfile +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/LICENSE +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/MANIFEST.in +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/README.md +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/README.rst +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/01_hello_bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/02_echo_bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/03_command_bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/04_private_only.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/05_group_only.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/06_regex_bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/07_user_filter.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/08_combined_filters.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/09_inline_keyboard.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/10_reply_keyboard.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/11_message_actions.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/12_media_bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/13_fsm_bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/14_plugin_bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/15_middleware_bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/16_scheduler_bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/17_conversation.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/18_chat_management.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/19_event_types.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/20_sync_bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/21_album_handler.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/22_download_bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/23_url_button.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/24_string_session.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/25_error_handling.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/25_working_bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/26_message_entities.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/27_search_messages.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/28_poll_bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/29_dice_bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/30_cache_bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/31_reaction_bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/32_mark_read_bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/33_context_manager.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/34_user_info.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/35_chat_info.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/36_forward_copy.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/37_admin_bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/38_media_filters.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/39_status_bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/40_delete_detection.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/41_read_detection.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/42_raw_events.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/43_poll_handler.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/44_reaction_handler.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/45_typing_handler.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/46_get_messages.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/47_iter_messages.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/48_get_members.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/49_resolve_username.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/examples/50_invoke.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/_updates/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/_updates/entitycache.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/_updates/messagebox.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/_updates/session.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/account.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/auth.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/bots.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/buttons.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/chats.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/dialogs.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/downloads.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/messageparse.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/messages.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/soroushclient.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/telegrambaseclient.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/updates.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/uploads.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/client/users.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/crypto/aes.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/crypto/aesctr.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/crypto/authkey.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/crypto/cdndecrypter.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/crypto/factorization.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/crypto/libssl.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/crypto/rsa.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/custom.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/errors/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/errors/common.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/errors/rpcbaseerrors.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/errors/rpcerrorlist.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/album.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/callbackquery.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/chataction.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/common.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/inlinequery.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/messagedeleted.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/messageedited.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/messageread.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/newmessage.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/raw.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/events/userupdate.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/extensions/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/extensions/html.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/extensions/markdown.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/extensions/messagepacker.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/functions.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/helpers.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/hints.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/authenticator.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/connection/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/connection/connection.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/connection/http.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/connection/tcpabridged.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/connection/tcpfull.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/connection/tcpintermediate.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/connection/tcpmtproxy.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/connection/tcpobfuscated.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/connection/websocket.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/mtprotoplainsender.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/mtprotostate.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/network/requeststate.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/password.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/requestiter.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/sessions/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/sessions/abstract.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/sessions/memory.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/sessions/sqlite.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/sessions/string.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/sync.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/alltlobjects.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/core/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/core/gzippacked.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/core/messagecontainer.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/core/rpcresult.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/core/tlmessage.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/adminlogevent.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/button.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/chatgetter.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/conversation.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/dialog.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/draft.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/file.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/forward.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/inlinebuilder.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/inlineresult.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/inlineresults.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/inputsizedfile.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/message.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/messagebutton.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/participantpermissions.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/qrlogin.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/sendergetter.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/custom/types.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/account.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/auth.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/bots.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/channels.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/chatlists.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/conference.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/contacts.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/folders.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/help.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/langpack.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/messages.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/payments.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/phone.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/photos.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/premium.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/stats.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/stories.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/thirdParty.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/updates.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/upload.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/functions/users.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/patched/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/tlobject.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/account.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/auth.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/bots.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/channels.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/chatlists.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/conference.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/contacts.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/help.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/messages.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/payments.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/phone.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/photos.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/premium.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/stats.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/stickers.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/storage.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/stories.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/thirdParty.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/update.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/updates.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/upload.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/tl/types/users.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/types.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/utils.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/_engine/version.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/admin.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/afk.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/cli.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/client/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/client/conversation.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/compat.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/config.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/errors/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/errors/exceptions.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/album.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/base.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/callback.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/chat_action.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/edited.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/inline.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/message.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/message_deleted.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/message_read.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/events/user_update.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/filters/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/filters/filters.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/fsm/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/fsm/state.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/middleware/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/middleware/base.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/middleware/rate_limit.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/mirror.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/models/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/models/bot.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/models/chat.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/models/enums.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/models/media.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/models/message.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/models/objects.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/models/user.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/network/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/network/client.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/network/connection.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/network/http_client.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/network/mtproto.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/network/protocols.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/network/spluspy_adapter.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/network/transport.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/plugins/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/plugins/loader.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/py.typed +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/scheduler/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/scheduler/scheduler.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/session/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/session/base.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/session/memory.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/session/sqlite.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/session/string.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/storage/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/storage/base.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/storage/entity_cache.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/storage/memory.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/storage/postgres.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/storage/redis.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/storage/sqlite.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/sync/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/sync/client.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/batch.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/cache.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/chat_lock.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/file_transfer.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/helpers.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/logger.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/rate_limiter.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/resolver.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/spluspy/utils/version_check.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/tests/__init__.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_client.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_filters.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_fsm.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_fsm_enhanced.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_middleware.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_rate_limiter.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_resolver.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_scheduler.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_session.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_storage.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_types.py +0 -0
- {spluspy-2.0.7 → spluspy-2.0.8}/tests/test_utils.py +0 -0
|
@@ -5,10 +5,11 @@ All notable changes to SplusPy will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
7
|
|
|
8
|
-
## [2.0.
|
|
8
|
+
## [2.0.8] - 2026-07-12
|
|
9
9
|
|
|
10
10
|
### Changed
|
|
11
|
-
- Version bump to 2.0.
|
|
11
|
+
- Version bump to 2.0.8
|
|
12
|
+
- Downgraded verbose internal warnings (USER_ALREADY_JOINED, missing access_hash, TypeNotFoundError) from WARNING to DEBUG level to reduce log noise
|
|
12
13
|
|
|
13
14
|
## [2.0.6] - 2026-07-11
|
|
14
15
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: spluspy
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.8
|
|
4
4
|
Summary: A modern async Python library for interacting with Soroush Plus
|
|
5
5
|
Project-URL: Homepage, https://github.com/Itskillmaster/spluspy
|
|
6
6
|
Project-URL: Documentation, https://github.com/Itskillmaster/spluspy#readme
|
spluspy-2.0.8/setup.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""
|
|
2
|
+
setup.py — Build script for spluspy Cython extensions.
|
|
3
|
+
|
|
4
|
+
Build locally with:
|
|
5
|
+
|
|
6
|
+
pip install cython cryptography
|
|
7
|
+
python setup.py build_ext --inplace
|
|
8
|
+
|
|
9
|
+
Or install in editable/development mode:
|
|
10
|
+
|
|
11
|
+
pip install -e ".[speed]"
|
|
12
|
+
|
|
13
|
+
The compiled ``.so`` / ``.pyd`` modules are placed alongside the source
|
|
14
|
+
``.pyx`` files so the dispatcher in ``__init__.py`` can find them at
|
|
15
|
+
import time.
|
|
16
|
+
"""
|
|
17
|
+
from setuptools import setup, Extension
|
|
18
|
+
from Cython.Build import cythonize
|
|
19
|
+
|
|
20
|
+
extensions = [
|
|
21
|
+
Extension(
|
|
22
|
+
"spluspy._engine.crypto.fast_aes",
|
|
23
|
+
sources=["spluspy/_engine/crypto/fast_aes.pyx"],
|
|
24
|
+
# No extra link flags needed — OpenSSL is loaded at runtime via
|
|
25
|
+
# the cryptography library's bundled libcrypto or via ctypes.
|
|
26
|
+
),
|
|
27
|
+
Extension(
|
|
28
|
+
"spluspy._engine.crypto.fast_rsa",
|
|
29
|
+
sources=["spluspy/_engine/crypto/fast_rsa.pyx"],
|
|
30
|
+
# The cryptography package is a runtime dependency of this module.
|
|
31
|
+
# It is listed in pyproject.toml under [project.optional-dependencies]
|
|
32
|
+
# under the "crypto" extra.
|
|
33
|
+
),
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
setup(
|
|
37
|
+
ext_modules=cythonize(
|
|
38
|
+
extensions,
|
|
39
|
+
compiler_directives={
|
|
40
|
+
"language_level": "3", # Python 3 semantics
|
|
41
|
+
"boundscheck": False, # skip bounds checks for speed
|
|
42
|
+
"wraparound": False, # skip negative-index wrapping
|
|
43
|
+
"cdivision": True, # use C division (no ZeroDivisionError)
|
|
44
|
+
"initializedcheck": False, # skip memoryview init checks
|
|
45
|
+
"nonecheck": False, # skip None checks on typed vars
|
|
46
|
+
},
|
|
47
|
+
),
|
|
48
|
+
)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module contains several utilities regarding cryptographic purposes,
|
|
3
|
+
such as the AES IGE mode used by SoroushPlus, the authorization key bound with
|
|
4
|
+
their data centers, and so on.
|
|
5
|
+
|
|
6
|
+
Dispatching strategy
|
|
7
|
+
--------------------
|
|
8
|
+
The ``AES`` class and the ``rsa`` submodule are resolved at import time
|
|
9
|
+
using a two-tier fallback:
|
|
10
|
+
|
|
11
|
+
1. **Fast path** – compiled Cython extensions (``fast_aes`` / ``fast_rsa``)
|
|
12
|
+
backed by OpenSSL via the ``cryptography`` library.
|
|
13
|
+
2. **Pure-Python path** – ``aes`` (``pyaes`` / ``cryptg`` / ``libssl``) and
|
|
14
|
+
``rsa`` (``rsa`` package).
|
|
15
|
+
|
|
16
|
+
If the compiled extensions are not available (the ``.so`` / ``.pyd`` files
|
|
17
|
+
have not been built, or a required dependency is missing), the dispatcher
|
|
18
|
+
silently falls back to the pure-Python implementations.
|
|
19
|
+
"""
|
|
20
|
+
import sys as _sys
|
|
21
|
+
import logging as _logging
|
|
22
|
+
|
|
23
|
+
_log = _logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
# ---------------------------------------------------------------------------
|
|
26
|
+
# AES dispatcher — prefers Cython fast_aes, falls back to pure-Python aes
|
|
27
|
+
# ---------------------------------------------------------------------------
|
|
28
|
+
try:
|
|
29
|
+
from .fast_aes import encrypt_ige as _fast_encrypt_ige
|
|
30
|
+
from .fast_aes import decrypt_ige as _fast_decrypt_ige
|
|
31
|
+
|
|
32
|
+
class AES:
|
|
33
|
+
"""
|
|
34
|
+
AES-IGE encryption / decryption interface.
|
|
35
|
+
|
|
36
|
+
When the Cython ``fast_aes`` extension is available the operations
|
|
37
|
+
are dispatched to OpenSSL (via the ``cryptography`` library) through
|
|
38
|
+
a Cython-typed wrapper. Otherwise the pure-Python ``aes.AES``
|
|
39
|
+
implementation is used.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
__slots__ = () # no instance state — all methods are static
|
|
43
|
+
|
|
44
|
+
@staticmethod
|
|
45
|
+
def encrypt_ige(plain_text: bytes, key: bytes, iv: bytes) -> bytes:
|
|
46
|
+
"""Encrypt *plain_text* using AES-IGE."""
|
|
47
|
+
return _fast_encrypt_ige(plain_text, key, iv)
|
|
48
|
+
|
|
49
|
+
@staticmethod
|
|
50
|
+
def decrypt_ige(cipher_text: bytes, key: bytes, iv: bytes) -> bytes:
|
|
51
|
+
"""Decrypt *cipher_text* using AES-IGE."""
|
|
52
|
+
return _fast_decrypt_ige(cipher_text, key, iv)
|
|
53
|
+
|
|
54
|
+
_log.debug('fast_aes Cython extension loaded – using OpenSSL AES-IGE')
|
|
55
|
+
|
|
56
|
+
except ImportError:
|
|
57
|
+
from .aes import AES
|
|
58
|
+
_log.debug('fast_aes not available – using pure-Python AES fallback')
|
|
59
|
+
|
|
60
|
+
# ---------------------------------------------------------------------------
|
|
61
|
+
# RSA dispatcher — prefers Cython fast_rsa, falls back to pure-Python rsa
|
|
62
|
+
#
|
|
63
|
+
# Consumers typically ``from ..crypto import rsa`` which resolves the
|
|
64
|
+
# submodule *rsa*. By injecting ``fast_rsa`` into ``sys.modules`` under
|
|
65
|
+
# the same dotted name *before* any other code imports ``.rsa``, we can
|
|
66
|
+
# transparently swap in the faster implementation.
|
|
67
|
+
# ---------------------------------------------------------------------------
|
|
68
|
+
_RSA_PKG = f'{__name__}.rsa' # e.g. "spluspy._engine.crypto.rsa"
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
from . import fast_rsa as _fast_rsa # noqa: F401 — triggers import
|
|
72
|
+
|
|
73
|
+
# Only replace if the original rsa module hasn't been imported yet.
|
|
74
|
+
if _RSA_PKG not in _sys.modules:
|
|
75
|
+
_sys.modules[_RSA_PKG] = _fast_rsa
|
|
76
|
+
_log.debug('fast_rsa Cython extension loaded – using OpenSSL RSA')
|
|
77
|
+
except ImportError:
|
|
78
|
+
_log.debug('fast_rsa not available – using pure-Python RSA fallback')
|
|
79
|
+
|
|
80
|
+
# ---------------------------------------------------------------------------
|
|
81
|
+
# Other submodules — always imported directly (no fast variant yet)
|
|
82
|
+
# ---------------------------------------------------------------------------
|
|
83
|
+
from .aesctr import AESModeCTR
|
|
84
|
+
from .authkey import AuthKey
|
|
85
|
+
from .factorization import Factorization
|
|
86
|
+
from .cdndecrypter import CdnDecrypter
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# cython: language_level=3, boundscheck=False, wraparound=False
|
|
2
|
+
"""
|
|
3
|
+
High-performance AES-IGE encryption/decryption using OpenSSL via Cython.
|
|
4
|
+
|
|
5
|
+
This module provides AES-IGE encrypt/decrypt optimized with:
|
|
6
|
+
- Direct OpenSSL calls via the ``cryptography`` library's bundled bindings
|
|
7
|
+
(falls back to ``ctypes.util.find_library`` if unavailable).
|
|
8
|
+
- C-level ``malloc``/``memcpy``/``free`` for buffer management, avoiding
|
|
9
|
+
intermediate Python objects in the hot path.
|
|
10
|
+
|
|
11
|
+
Falls back gracefully: if neither the ``cryptography`` library nor a
|
|
12
|
+
system OpenSSL is reachable, an ``ImportError`` is raised at import time
|
|
13
|
+
so the dispatcher in ``__init__.py`` can select the pure-Python path.
|
|
14
|
+
"""
|
|
15
|
+
import ctypes
|
|
16
|
+
import ctypes.util
|
|
17
|
+
import os
|
|
18
|
+
import sys
|
|
19
|
+
from libc.stdlib cimport malloc, free
|
|
20
|
+
from libc.string cimport memcpy
|
|
21
|
+
|
|
22
|
+
# ---------------------------------------------------------------------------
|
|
23
|
+
# OpenSSL loading
|
|
24
|
+
# ---------------------------------------------------------------------------
|
|
25
|
+
cdef bint _loaded = False
|
|
26
|
+
cdef object _lib = None # ctypes CDLL handle
|
|
27
|
+
cdef object _AES_set_encrypt_key = None
|
|
28
|
+
cdef object _AES_set_decrypt_key = None
|
|
29
|
+
cdef object _AES_ige_encrypt = None
|
|
30
|
+
|
|
31
|
+
# AES_KEY struct size (AES-256: 4*(14+1)*4 = 240 bytes rd_key + 4 bytes rounds)
|
|
32
|
+
cdef int _AES_KEY_SIZE = 260
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
cdef void _ensure_openssl():
|
|
36
|
+
"""Lazily load OpenSSL and configure ctypes function signatures."""
|
|
37
|
+
global _loaded, _lib
|
|
38
|
+
global _AES_set_encrypt_key, _AES_set_decrypt_key, _AES_ige_encrypt
|
|
39
|
+
if _loaded:
|
|
40
|
+
return
|
|
41
|
+
_loaded = True
|
|
42
|
+
|
|
43
|
+
# --- Strategy 1: use the cryptography library's bundled OpenSSL ---
|
|
44
|
+
try:
|
|
45
|
+
from cryptography.hazmat.bindings.openssl import binding
|
|
46
|
+
_lib = binding.Binding.lib
|
|
47
|
+
except Exception:
|
|
48
|
+
_lib = None
|
|
49
|
+
|
|
50
|
+
# --- Strategy 2: fall back to system OpenSSL ---
|
|
51
|
+
if _lib is None:
|
|
52
|
+
try:
|
|
53
|
+
_lib = ctypes.cdll.LoadLibrary(
|
|
54
|
+
ctypes.util.find_library('ssl')
|
|
55
|
+
or ctypes.util.find_library('crypto')
|
|
56
|
+
)
|
|
57
|
+
except OSError:
|
|
58
|
+
_lib = None
|
|
59
|
+
|
|
60
|
+
if _lib is None:
|
|
61
|
+
return
|
|
62
|
+
|
|
63
|
+
# Configure AES_set_encrypt_key
|
|
64
|
+
_AES_set_encrypt_key = _lib.AES_set_encrypt_key
|
|
65
|
+
_AES_set_encrypt_key.restype = ctypes.c_int
|
|
66
|
+
_AES_set_encrypt_key.argtypes = [
|
|
67
|
+
ctypes.c_char_p, # const unsigned char *userKey
|
|
68
|
+
ctypes.c_int, # int bits
|
|
69
|
+
ctypes.c_void_p, # AES_KEY *aesKey
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
# Configure AES_set_decrypt_key
|
|
73
|
+
_AES_set_decrypt_key = _lib.AES_set_decrypt_key
|
|
74
|
+
_AES_set_decrypt_key.restype = ctypes.c_int
|
|
75
|
+
_AES_set_decrypt_key.argtypes = [
|
|
76
|
+
ctypes.c_char_p, # const unsigned char *userKey
|
|
77
|
+
ctypes.c_int, # int bits
|
|
78
|
+
ctypes.c_void_p, # AES_KEY *aesKey
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
# Configure AES_ige_encrypt — use c_void_p for all pointer args so we
|
|
82
|
+
# can pass integer addresses from Cython malloc'd buffers.
|
|
83
|
+
_AES_ige_encrypt = _lib.AES_ige_encrypt
|
|
84
|
+
_AES_ige_encrypt.restype = None
|
|
85
|
+
_AES_ige_encrypt.argtypes = [
|
|
86
|
+
ctypes.c_void_p, # const unsigned char *in
|
|
87
|
+
ctypes.c_void_p, # unsigned char *out
|
|
88
|
+
ctypes.c_size_t, # size_t length
|
|
89
|
+
ctypes.c_void_p, # AES_KEY *key
|
|
90
|
+
ctypes.c_void_p, # unsigned char *iv (32 bytes)
|
|
91
|
+
ctypes.c_int, # int enc (1=encrypt, 0=decrypt)
|
|
92
|
+
]
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
# ---------------------------------------------------------------------------
|
|
96
|
+
# Public API
|
|
97
|
+
# ---------------------------------------------------------------------------
|
|
98
|
+
|
|
99
|
+
def encrypt_ige(bytes plain_text, bytes key, bytes iv) -> bytes:
|
|
100
|
+
"""
|
|
101
|
+
AES-IGE *encrypt* using OpenSSL.
|
|
102
|
+
|
|
103
|
+
:param plain_text: plaintext (will be padded to a 16-byte boundary).
|
|
104
|
+
:param key: AES key (16, 24 or 32 bytes).
|
|
105
|
+
:param iv: 32-byte IGE initialization vector.
|
|
106
|
+
:returns: ciphertext bytes.
|
|
107
|
+
:raises RuntimeError: if OpenSSL is not available.
|
|
108
|
+
"""
|
|
109
|
+
_ensure_openssl()
|
|
110
|
+
if _AES_ige_encrypt is None:
|
|
111
|
+
raise RuntimeError(
|
|
112
|
+
"OpenSSL AES_ige_encrypt is not available. "
|
|
113
|
+
"Install the ``cryptography`` package or ensure libssl/libcrypto "
|
|
114
|
+
"is reachable via ctypes."
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# Pad plaintext to 16-byte boundary (matches existing aes.py behaviour)
|
|
118
|
+
cdef Py_ssize_t pt_len = len(plain_text)
|
|
119
|
+
cdef int remainder = pt_len % 16
|
|
120
|
+
if remainder:
|
|
121
|
+
plain_text = plain_text + os.urandom(16 - remainder)
|
|
122
|
+
pt_len = len(plain_text)
|
|
123
|
+
|
|
124
|
+
# Allocate C-level buffers via libc (no Python object overhead)
|
|
125
|
+
cdef unsigned char *in_buf = <unsigned char *>malloc(pt_len)
|
|
126
|
+
cdef unsigned char *out_buf = <unsigned char *>malloc(pt_len)
|
|
127
|
+
cdef unsigned char *aes_key = <unsigned char *>malloc(_AES_KEY_SIZE)
|
|
128
|
+
|
|
129
|
+
if in_buf == NULL or out_buf == NULL or aes_key == NULL:
|
|
130
|
+
free(in_buf)
|
|
131
|
+
free(out_buf)
|
|
132
|
+
free(aes_key)
|
|
133
|
+
raise MemoryError("Failed to allocate buffers for AES-IGE")
|
|
134
|
+
|
|
135
|
+
cdef int rc = 0
|
|
136
|
+
cdef const unsigned char[:] pt_view = plain_text
|
|
137
|
+
cdef const unsigned char[:] iv_view = iv
|
|
138
|
+
|
|
139
|
+
try:
|
|
140
|
+
# Copy plaintext into C buffer
|
|
141
|
+
memcpy(in_buf, &pt_view[0], <size_t>pt_len)
|
|
142
|
+
|
|
143
|
+
# Set up AES encrypt key schedule
|
|
144
|
+
# key is passed as bytes (ctypes c_char_p); aes_key as void* integer
|
|
145
|
+
rc = _AES_set_encrypt_key(key, <int>(len(key) * 8), <size_t>aes_key)
|
|
146
|
+
if rc != 0:
|
|
147
|
+
raise RuntimeError(f"AES_set_encrypt_key failed (rc={rc})")
|
|
148
|
+
|
|
149
|
+
# Perform IGE encryption — all pointer args as integer addresses
|
|
150
|
+
_AES_ige_encrypt(
|
|
151
|
+
<size_t>in_buf,
|
|
152
|
+
<size_t>out_buf,
|
|
153
|
+
<size_t>pt_len,
|
|
154
|
+
<size_t>aes_key,
|
|
155
|
+
<size_t>&iv_view[0],
|
|
156
|
+
<int>1, # AES_ENCRYPT
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
# Build Python bytes from C buffer
|
|
160
|
+
return bytes(out_buf[:pt_len])
|
|
161
|
+
finally:
|
|
162
|
+
free(in_buf)
|
|
163
|
+
free(out_buf)
|
|
164
|
+
free(aes_key)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def decrypt_ige(bytes cipher_text, bytes key, bytes iv) -> bytes:
|
|
168
|
+
"""
|
|
169
|
+
AES-IGE *decrypt* using OpenSSL.
|
|
170
|
+
|
|
171
|
+
:param cipher_text: ciphertext (must be a multiple of 16 bytes).
|
|
172
|
+
:param key: AES key (16, 24 or 32 bytes).
|
|
173
|
+
:param iv: 32-byte IGE initialization vector.
|
|
174
|
+
:returns: plaintext bytes.
|
|
175
|
+
:raises RuntimeError: if OpenSSL is not available.
|
|
176
|
+
"""
|
|
177
|
+
_ensure_openssl()
|
|
178
|
+
if _AES_ige_encrypt is None:
|
|
179
|
+
raise RuntimeError(
|
|
180
|
+
"OpenSSL AES_ige_encrypt is not available. "
|
|
181
|
+
"Install the ``cryptography`` package or ensure libssl/libcrypto "
|
|
182
|
+
"is reachable via ctypes."
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
cdef Py_ssize_t ct_len = len(cipher_text)
|
|
186
|
+
|
|
187
|
+
# Allocate C-level buffers
|
|
188
|
+
cdef unsigned char *in_buf = <unsigned char *>malloc(ct_len)
|
|
189
|
+
cdef unsigned char *out_buf = <unsigned char *>malloc(ct_len)
|
|
190
|
+
cdef unsigned char *aes_key = <unsigned char *>malloc(_AES_KEY_SIZE)
|
|
191
|
+
|
|
192
|
+
if in_buf == NULL or out_buf == NULL or aes_key == NULL:
|
|
193
|
+
free(in_buf)
|
|
194
|
+
free(out_buf)
|
|
195
|
+
free(aes_key)
|
|
196
|
+
raise MemoryError("Failed to allocate buffers for AES-IGE")
|
|
197
|
+
|
|
198
|
+
cdef int rc = 0
|
|
199
|
+
cdef const unsigned char[:] ct_view = cipher_text
|
|
200
|
+
cdef const unsigned char[:] iv_view = iv
|
|
201
|
+
|
|
202
|
+
try:
|
|
203
|
+
# Copy ciphertext into C buffer
|
|
204
|
+
memcpy(in_buf, &ct_view[0], <size_t>ct_len)
|
|
205
|
+
|
|
206
|
+
# Set up AES decrypt key schedule
|
|
207
|
+
rc = _AES_set_decrypt_key(key, <int>(len(key) * 8), <size_t>aes_key)
|
|
208
|
+
if rc != 0:
|
|
209
|
+
raise RuntimeError(f"AES_set_decrypt_key failed (rc={rc})")
|
|
210
|
+
|
|
211
|
+
# Perform IGE decryption
|
|
212
|
+
_AES_ige_encrypt(
|
|
213
|
+
<size_t>in_buf,
|
|
214
|
+
<size_t>out_buf,
|
|
215
|
+
<size_t>ct_len,
|
|
216
|
+
<size_t>aes_key,
|
|
217
|
+
<size_t>&iv_view[0],
|
|
218
|
+
<int>0, # AES_DECRYPT
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
# Build Python bytes from C buffer
|
|
222
|
+
return bytes(out_buf[:ct_len])
|
|
223
|
+
finally:
|
|
224
|
+
free(in_buf)
|
|
225
|
+
free(out_buf)
|
|
226
|
+
free(aes_key)
|