Compare commits

...

No commits in common. 'main' and 'annn' have entirely different histories.

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MaterialThemeProjectNewConfig">
<option name="metadata">
<MTProjectMetadataState>
<option name="migrated" value="true" />
<option name="pristineConfig" value="false" />
<option name="userId" value="-255eb2d9:193864c0364:-7ffe" />
</MTProjectMetadataState>
</option>
</component>
</project>

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.13" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13" project-jdk-type="Python SDK" />
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

@ -0,0 +1,343 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="b490c3d2-83ec-4ee0-b2e3-44d7951d4337" name="更改" comment="已成功实现在虚拟机和物理机之间运行">
<change afterPath="$PROJECT_DIR$/ui.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/private.pem" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/public.pem" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/receiver_private.pem" beforeDir="false" afterPath="$PROJECT_DIR$/receiver_private.pem" afterDir="false" />
<change beforePath="$PROJECT_DIR$/receiver_public.pem" beforeDir="false" afterPath="$PROJECT_DIR$/receiver_public.pem" afterDir="false" />
<change beforePath="$PROJECT_DIR$/sender_private.pem" beforeDir="false" afterPath="$PROJECT_DIR$/sender_private.pem" afterDir="false" />
<change beforePath="$PROJECT_DIR$/sender_public.pem" beforeDir="false" afterPath="$PROJECT_DIR$/sender_public.pem" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Python Script" />
</list>
</option>
</component>
<component name="Git.Settings">
<option name="PUSH_TAGS">
<GitPushTagMode>
<option name="argument" value="--tags" />
<option name="title" value="All" />
</GitPushTagMode>
</option>
<option name="RECENT_BRANCH_BY_REPOSITORY">
<map>
<entry key="$PROJECT_DIR$" value="master" />
</map>
</option>
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="GitHubPullRequestSearchHistory">{
&quot;history&quot;: [
{
&quot;assignee&quot;: &quot;vernuser&quot;
}
],
&quot;lastFilter&quot;: {
&quot;assignee&quot;: &quot;vernuser&quot;
}
}</component>
<component name="GithubPullRequestsUISettings">{
&quot;selectedUrlAndAccountId&quot;: {
&quot;url&quot;: &quot;https://github.com/vernuser/cryptography_homework.git&quot;,
&quot;accountId&quot;: &quot;8b7e9b97-86ab-4db0-a673-929e037f7c36&quot;
}
}</component>
<component name="ProjectColorInfo">{
&quot;associatedIndex&quot;: 6
}</component>
<component name="ProjectId" id="2q0CtQoODIzSL6TNpmKqHaR1R2h" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true">
<ConfirmationsSetting value="2" id="Add" />
</component>
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"Python.client.executor": "Run",
"Python.encryption_utils.executor": "Run",
"Python.file_transfer.executor": "Run",
"Python.generate_key.executor": "Run",
"Python.generate_keys.executor": "Run",
"Python.receiver.executor": "Run",
"Python.sender.executor": "Run",
"Python.server.executor": "Run",
"Python.ui.executor": "Run",
"Python.utils.executor": "Run",
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.git.unshallow": "true",
"git-widget-placeholder": "annn",
"last_opened_file_path": "C:/Users/Asus/Desktop/烽台校园实习/交接资料/实验室仿真台攻击脚本/实验室仿真台攻击脚本/仿真台攻击脚本11.22",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"vue.rearranger.settings.migration": "true"
}
}]]></component>
<component name="RunManager" selected="Python.ui">
<configuration name="generate_key" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="应用密码学课设" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/generate_key.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="sender" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="应用密码学课设" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/sender.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="server" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="应用密码学课设" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/server.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="ui" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="应用密码学课设" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/ui.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="utils" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="应用密码学课设" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/utils.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<recent_temporary>
<list>
<item itemvalue="Python.ui" />
<item itemvalue="Python.generate_key" />
<item itemvalue="Python.sender" />
<item itemvalue="Python.server" />
<item itemvalue="Python.utils" />
</list>
</recent_temporary>
</component>
<component name="SharedIndexes">
<attachedChunks>
<set>
<option value="bundled-js-predefined-d6986cc7102b-e768b9ed790e-JavaScript-PY-243.21565.199" />
<option value="bundled-python-sdk-cab1f2013843-4ae2d6a61b08-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-243.21565.199" />
</set>
</attachedChunks>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="应用程序级" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="默认任务">
<changelist id="b490c3d2-83ec-4ee0-b2e3-44d7951d4337" name="更改" comment="" />
<created>1733790319291</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1733790319291</updated>
<workItem from="1733790320526" duration="16500000" />
<workItem from="1733816283165" duration="11000" />
<workItem from="1733816653982" duration="19000" />
<workItem from="1734342680147" duration="380000" />
<workItem from="1734406816783" duration="1550000" />
<workItem from="1734436439919" duration="90000" />
<workItem from="1734488993135" duration="581000" />
<workItem from="1734607228597" duration="4000" />
<workItem from="1734770663055" duration="28000" />
<workItem from="1734779266249" duration="2176000" />
</task>
<task id="LOCAL-00001" summary="加了互传">
<option name="closed" value="true" />
<created>1733793465023</created>
<option name="number" value="00001" />
<option name="presentableId" value="LOCAL-00001" />
<option name="project" value="LOCAL" />
<updated>1733793465023</updated>
</task>
<task id="LOCAL-00002" summary="加了中文">
<option name="closed" value="true" />
<created>1733801157608</created>
<option name="number" value="00002" />
<option name="presentableId" value="LOCAL-00002" />
<option name="project" value="LOCAL" />
<updated>1733801157608</updated>
</task>
<task id="LOCAL-00003" summary="签名错误?">
<option name="closed" value="true" />
<created>1733810790769</created>
<option name="number" value="00003" />
<option name="presentableId" value="LOCAL-00003" />
<option name="project" value="LOCAL" />
<updated>1733810790769</updated>
</task>
<task id="LOCAL-00004" summary="已成功实现在虚拟机和物理机之间运行">
<option name="closed" value="true" />
<created>1733815825091</created>
<option name="number" value="00004" />
<option name="presentableId" value="LOCAL-00004" />
<option name="project" value="LOCAL" />
<updated>1733815825091</updated>
</task>
<task id="LOCAL-00005" summary="已成功实现在虚拟机和物理机之间运行">
<option name="closed" value="true" />
<created>1734489312302</created>
<option name="number" value="00005" />
<option name="presentableId" value="LOCAL-00005" />
<option name="project" value="LOCAL" />
<updated>1734489312302</updated>
</task>
<task id="LOCAL-00006" summary="已成功实现在虚拟机和物理机之间运行">
<option name="closed" value="true" />
<created>1734489392435</created>
<option name="number" value="00006" />
<option name="presentableId" value="LOCAL-00006" />
<option name="project" value="LOCAL" />
<updated>1734489392435</updated>
</task>
<option name="localTasksCounter" value="7" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State>
<option name="FILTERS">
<map>
<entry key="branch">
<value>
<list>
<option value="annn" />
</list>
</value>
</entry>
</map>
</option>
</State>
</value>
</entry>
</map>
</option>
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="加了互传" />
<MESSAGE value="加了中文" />
<MESSAGE value="签名错误?" />
<MESSAGE value="已成功实现在虚拟机和物理机之间运行" />
<option name="LAST_COMMIT_MESSAGE" value="已成功实现在虚拟机和物理机之间运行" />
</component>
<component name="com.intellij.coverage.CoverageDataManagerImpl">
<SUITE FILE_PATH="coverage/$receiver.coverage" NAME="receiver 覆盖结果" MODIFIED="1734342809902" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/$file_transfer.coverage" NAME="file_transfer 覆盖结果" MODIFIED="1733810226775" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/$server.coverage" NAME="server 覆盖结果" MODIFIED="1734342831970" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/$utils.coverage" NAME="utils 覆盖结果" MODIFIED="1734342818616" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/$ui.coverage" NAME="ui 覆盖结果" MODIFIED="1734781859043" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/$generate_key.coverage" NAME="generate_key 覆盖结果" MODIFIED="1734781683799" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/$generate_keys.coverage" NAME="generate_keys 覆盖结果" MODIFIED="1733809016631" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/$encryption_utils.coverage" NAME="encryption_utils 覆盖结果" MODIFIED="1734342806348" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/$sender.coverage" NAME="sender 覆盖结果" MODIFIED="1734489006420" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/$client.coverage" NAME="client 覆盖结果" MODIFIED="1733809932519" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
</component>
</project>

@ -0,0 +1 @@
166666

@ -1,73 +0,0 @@
Creative Commons Attribution-NoDerivs 1.0
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DRAFT LICENSE DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ITS USE.
License
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE IS PROHIBITED.
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
1. Definitions
a. "Collective Work" means a work, such as a periodical issue, anthology or encyclopedia, in which the Work in its entirety in unmodified form, along with a number of other contributions, constituting separate and independent works in themselves, are assembled into a collective whole. A work that constitutes a Collective Work will not be considered a Derivative Work (as defined below) for the purposes of this License.
b. "Derivative Work" means a work based upon the Work or upon the Work and other pre-existing works, such as a translation, musical arrangement, dramatization, fictionalization, motion picture version, sound recording, art reproduction, abridgment, condensation, or any other form in which the Work may be recast, transformed, or adapted, except that a work that constitutes a Collective Work will not be considered a Derivative Work for the purpose of this License.
c. "Licensor" means the individual or entity that offers the Work under the terms of this License.
d. "Original Author" means the individual or entity who created the Work.
e. "Work" means the copyrightable work of authorship offered under the terms of this License.
f. "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.
2. Fair Use Rights. Nothing in this license is intended to reduce, limit, or restrict any rights arising from fair use, first sale or other limitations on the exclusive rights of the copyright owner under copyright law or other applicable laws.
3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:
a. to reproduce the Work, to incorporate the Work into one or more Collective Works, and to reproduce the Work as incorporated in the Collective Works;
b. to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission the Work including as incorporated in Collective Works;
The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. All rights not expressly granted by Licensor are hereby reserved.
4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:
a. You may distribute, publicly display, publicly perform, or publicly digitally perform the Work only under the terms of this License, and You must include a copy of, or the Uniform Resource Identifier for, this License with every copy or phonorecord of the Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Work that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Work itself to be made subject to the terms of this License. If You create a Collective Work, upon notice from any Licensor You must, to the extent practicable, remove from the Collective Work any reference to such Licensor or the Original Author, as requested.
b. If you distribute, publicly display, publicly perform, or publicly digitally perform the Work or any Collective Works, You must keep intact all copyright notices for the Work and give the Original Author credit reasonable to the medium or means You are utilizing by conveying the name (or pseudonym if applicable) of the Original Author if supplied; the title of the Work if supplied. Such credit may be implemented in any reasonable manner; provided, however, that in the case of a Collective Work, at a minimum such credit will appear where any other comparable authorship credit appears and in a manner at least as prominent as such other comparable authorship credit.
5. Representations, Warranties and Disclaimer
a. By offering the Work for public release under this License, Licensor represents and warrants that, to the best of Licensor's knowledge after reasonable inquiry:
i. Licensor has secured all rights in the Work necessary to grant the license rights hereunder and to permit the lawful exercise of the rights granted hereunder without You having any obligation to pay any royalties, compulsory license fees, residuals or any other payments;
ii. The Work does not infringe the copyright, trademark, publicity rights, common law rights or any other right of any third party or constitute defamation, invasion of privacy or other tortious injury to any third party.
b. EXCEPT AS EXPRESSLY STATED IN THIS LICENSE OR OTHERWISE AGREED IN WRITING OR REQUIRED BY APPLICABLE LAW, THE WORK IS LICENSED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES REGARDING THE CONTENTS OR ACCURACY OF THE WORK.
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, AND EXCEPT FOR DAMAGES ARISING FROM LIABILITY TO A THIRD PARTY RESULTING FROM BREACH OF THE WARRANTIES IN SECTION 5, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
7. Termination
a. This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Collective Works from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.
b. Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.
8. Miscellaneous
a. Each time You distribute or publicly digitally perform the Work or a Collective Work, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.
b. If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
c. No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.
d. This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.
Creative Commons is not a party to this License, and makes no warranty whatsoever in connection with the Work. Creative Commons will not be liable to You or any party on any legal theory for any damages whatsoever, including without limitation any general, special, incidental or consequential damages arising in connection to this license. Notwithstanding the foregoing two (2) sentences, if Creative Commons has expressly identified itself as the Licensor hereunder, it shall have all rights and obligations of Licensor.
Except for the limited purpose of indicating to the public that the Work is licensed under the CCPL, neither party will use the trademark "Creative Commons" or any related trademark or logo of Creative Commons without the prior written consent of Creative Commons. Any permitted use will be in compliance with Creative Commons' then-current trademark usage guidelines, as may be published on its website or otherwise made available upon request from time to time.
Creative Commons may be contacted at http://creativecommons.org/.

@ -1,2 +0,0 @@
# file_tran

@ -0,0 +1 @@
{"nonce": "viRm4Dv0Hc1LnifER06rOw==", "ciphertext": "4Q==", "tag": "HD05+MIgwuWKStAA1DAelA==", "encrypted_key": "YkZ48DIhZzn4mjkzyajDZ8QCDvLFvp3+5N9stM4Bk8elaroz8hPY0UFfewxfYrj0Uz8jimYYANULsXE9itCHKWIaZC+XIIBfd13+eh4rDGuFipXy1ua6EwGDM8arGass4Prwy3G9pxX8j4iPKHWSgfSeqfKpMMBTVqadO5zPFXUOxqFjDOoKAO2lYusOdCIN5/X0sNQd7Bbc9RS59vG8N6yOGagwaATtEciSYr/4SVaqUTlyGiyegOb8OSoplj7jOyOvbUsaHEy3mVE7q992zImyPm+mvQjbWHS0gat+vzTMWRTVmbd8AdnXy3xnCDKhizsowKBtu6x4ksct1u9A5Q==", "signature": "ZUD0Nb2/4AAQRW1KQZIPrlZI7MtPbjM144TP3uIsBwtVTEO2Ew1g5cEb/ZAGSzIlyAiyqN/HVPYOKqpmzdLDHZtn2bQB6AjphLTgl0wwLjOhVc7QLHddWBQoetEhetSXdNZqCaQRb05p0TCA4J01fThVDbmonpEoAaR4xkDPw2zQKIFnYohkQY7xpqOFHfVCa4v/98LgUKkGkMOVXxLqvgVuUwmCWw+Or3WcIA9pxz4438v/VC1fuYGzk3bXHfnSoDstrXCQvfpsQ22O9vY3wwb2gxSxOHZWMMn8b542tzGAw9Ul/x8yCnjcdF1GxbEHoljgR5iSlqsJ85r2WNIo6A==", "filename": "1.txt"}

@ -0,0 +1,56 @@
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP, AES
from Crypto.Random import get_random_bytes
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
class AsymmetricEncryption:
def __init__(self):
# 生成2048位的RSA密钥对
self.key_pair = RSA.generate(2048)
def get_public_key(self):
# 返回公钥
return self.key_pair.publickey()
def get_private_key(self):
# 返回私钥
return self.key_pair
def encrypt_with_public_key(self, data, public_key):
# 使用公钥加密数据
cipher_rsa = PKCS1_OAEP.new(public_key)
return cipher_rsa.encrypt(data)
def decrypt_with_private_key(self, encrypted_data):
# 使用私钥解密数据
cipher_rsa = PKCS1_OAEP.new(self.key_pair)
return cipher_rsa.decrypt(encrypted_data)
def sign_data(self, data):
# 对数据进行SHA256哈希然后使用私钥生成签名
h = SHA256.new(data)
signature = pkcs1_15.new(self.key_pair).sign(h)
return signature
def verify_signature(self, data, signature, public_key):
# 对数据进行SHA256哈希然后使用公钥验证签名
h = SHA256.new(data)
try:
pkcs1_15.new(public_key).verify(h, signature)
return True
except (ValueError, TypeError):
return False
class SymmetricEncryption:
def encrypt(self, data, key):
# 使用AES-GCM模式加密数据
cipher_aes = AES.new(key, AES.MODE_GCM)
nonce = cipher_aes.nonce
ciphertext, tag = cipher_aes.encrypt_and_digest(data)
return nonce, ciphertext, tag
def decrypt(self, nonce, ciphertext, tag, key):
# 使用AES-GCM模式解密数据并验证
cipher_aes = AES.new(key, AES.MODE_GCM, nonce=nonce)
return cipher_aes.decrypt_and_verify(ciphertext, tag)

@ -0,0 +1,9 @@
from utils import generate_rsa_keypair, save_key
sender_private, sender_public = generate_rsa_keypair()
receiver_private, receiver_public = generate_rsa_keypair()
save_key('sender_private.pem', sender_private)
save_key('sender_public.pem', sender_public)
save_key('receiver_private.pem', receiver_private)
save_key('receiver_public.pem', receiver_public)

@ -0,0 +1,55 @@
import json
import base64
import socket
from utils import aes_decrypt, rsa_decrypt, verify_signature, load_key
def receive_file(port, receiver_private_key, sender_public_key):
# 启动服务监听
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(('', port))
s.listen(1)
print(f"接收方正在监听端口 {port}...")
conn, addr = s.accept()
print(f"来自 {addr} 的连接已建立!")
with conn:
# 接收数据
data = conn.recv(65536) # 最大接收 64KB 数据
data_packet = json.loads(data.decode('utf-8'))
# 解码 Base64 数据
nonce = base64.b64decode(data_packet['nonce'])
ciphertext = base64.b64decode(data_packet['ciphertext'])
tag = base64.b64decode(data_packet['tag'])
encrypted_key = base64.b64decode(data_packet['encrypted_key'])
signature = base64.b64decode(data_packet['signature'])
filename = data_packet['filename']
# 使用接收方私钥解密AES密钥
aes_key = rsa_decrypt(encrypted_key, receiver_private_key)
# 使用AES密钥解密文件内容
try:
file_data = aes_decrypt(nonce, ciphertext, tag, aes_key)
# 验证签名
if verify_signature(sender_public_key, file_data, signature):
print("签名验证成功,文件未被篡改!")
# 保存解密后的文件
with open(f"received_{filename}", 'wb') as f:
f.write(file_data)
print(f"文件已保存为 received_{filename}")
else:
print("签名验证失败,文件可能被篡改!")
except Exception as e:
print(f"文件解密或验证过程中出错:{e}")
if __name__ == "__main__":
# 加载密钥
receiver_private_key = load_key('receiver_private.pem')
sender_public_key = load_key('sender_public.pem')
# 监听端口
port = 12345
receive_file(port, receiver_private_key, sender_public_key)

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAl4H8ztB6F4Smewf7OUpgQCm2iJST9+X+odvFV9lkA0cU3HLb
PV7O/dAC0jjVFOM1fNcklHxkJppH7kjJ31/XhfPvZpaShja6PZS2ffCPbQRBAcjh
Ps0gwzZMKe3qwUBZCAducFtgi7BXvNhRNfOMufPnuzHx//XJReQzJ6Z747jticAT
7nLIF2EM+vl24jsM1Gnm1LyMPV3gyxUamfqyLxyHr2WnqRNZs89CK4TnzrU9Jdw2
Y5BzED9J7mDqOIOyDnzJ+9q/EN/ciOpnS04YkZH26nuVN90RHnp37MY9z7p3o8j8
KRXir524o+UhBVgVkCS7zTmVorZsql7I2cx9GQIDAQABAoIBAAgL8QbbUkvmEWEV
NlXZHU3BfJg6N+k7Ismq6yTBMktTeG6q5PnLi5FpMLUq+PPJvqeZb5Zsf6jMzRQ0
c0OBvhsdrqUGsaDrzpScGnZYeYc2aiBAcIIa3lB8rxF50tvq4Uk7x86zQIHt+DYn
hDMQcw48DFGU+f+rqKhyUcTOouOgJxyUr7z9gnz1OH2SQImiYaEuVceNULGrvGd/
Zq1p7aqnm9WKwxX7oUXTBvx1s/EKsKPbWdLCNbHxLjYWfgEiErRi6ghLfGUhaKWu
oSq38Cjqg9OCUmzjurfAvmZws4zCRthGuBW3EyAgHlt6S+JhoKoNg06zGso8uScq
4+BrOCcCgYEAvlRpCZ7y4L8Nq4XEToK41nnsLUKgkXmQ5D1xUrz91F3SYMOdRa+M
aQcHyhpyRI4mzAf/rxMBitXfTQzqzZkrX2QbAo450czOjHkdEKTRe8lfBXKnb0mz
TAhpePDayENoPQeXH2BLUT8xMiJE/bCURGR4U5UPiH95X7ZzC9/3abMCgYEAy8h7
KnXUXGZUJFycI7nPXCNY26OqatqKKYpWSNnzJRKO73JzP5SFmtUinASi9jB/m8Vz
FWq5bcumS9KTLcAAjgeLWsRijvnBB2dmZYDq+TLxEfXDGr4lj/amOq87D7VjgVSV
VQp1UpAGQfHdJFF72Lm4HnML1qC5z78aQRrgwAMCgYEAt+xUEJMEO8EEUcMTX5cd
TU1GuLoQ9mOWa6kgcIbndygvG4kM2wF4WyoLEfeagrsnrLTyFNn1/JcOkaOw53tj
mWvgWgjcwOv8kWycdLABK3D+HQKd4IJE/G2IlvGRSkMxYQCLvitMvTemr77EEq9n
p+u7B3IdL5eXz7E83bXRndcCgYEAgxQKvW4bUe/0UYtMV+KOEfsejfEBjkfSNRQp
miSvNHpyfGzG2u/C3KwZ3fdRhz/85QqlkvIaIhird/wT9YqaEMGjjpfhuYvG8Oc+
wy2gdvigfefyPoJukOKbXAYY3GrVfXwVriTTAG9pxwM3NsQ/AFG9r8BargymWI3Y
6mXKiVcCgYAp1OLouyd0RzAjazUHXjvo4/vrwLlKzZy/rKLHAxsyoNF4CI1x3SOQ
QbmWRSFSm2Ki/iNEqI5YDirgNX953REQUUgY3vbYx0Uvjko/xqVqV2aUQRkqiuD8
eWDP/MNdviC8Xh8EJxCNdbcRt54xa50XRzhcQysMPo7wBJ2PXoZ1gg==
-----END RSA PRIVATE KEY-----

@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl4H8ztB6F4Smewf7OUpg
QCm2iJST9+X+odvFV9lkA0cU3HLbPV7O/dAC0jjVFOM1fNcklHxkJppH7kjJ31/X
hfPvZpaShja6PZS2ffCPbQRBAcjhPs0gwzZMKe3qwUBZCAducFtgi7BXvNhRNfOM
ufPnuzHx//XJReQzJ6Z747jticAT7nLIF2EM+vl24jsM1Gnm1LyMPV3gyxUamfqy
LxyHr2WnqRNZs89CK4TnzrU9Jdw2Y5BzED9J7mDqOIOyDnzJ+9q/EN/ciOpnS04Y
kZH26nuVN90RHnp37MY9z7p3o8j8KRXir524o+UhBVgVkCS7zTmVorZsql7I2cx9
GQIDAQAB
-----END PUBLIC KEY-----

@ -0,0 +1,53 @@
import os
import json
import base64
import socket
from utils import aes_encrypt, rsa_encrypt, generate_signature, load_key
def send_file(filename, receiver_ip, receiver_port, receiver_public_key, sender_private_key):
# 读取文件内容
with open(filename, 'rb') as f:
file_data = f.read()
# 生成随机AES密钥
aes_key = os.urandom(16)
# 加密文件
nonce, ciphertext, tag = aes_encrypt(file_data, aes_key)
# 使用接收方公钥加密AES密钥
encrypted_aes_key = rsa_encrypt(aes_key, receiver_public_key)
# 生成数字签名(针对原始文件内容)
signature = generate_signature(sender_private_key, file_data)
# 使用 Base64 对所有数据进行编码
data_packet = {
'nonce': base64.b64encode(nonce).decode(),
'ciphertext': base64.b64encode(ciphertext).decode(),
'tag': base64.b64encode(tag).decode(),
'encrypted_key': base64.b64encode(encrypted_aes_key).decode(),
'signature': base64.b64encode(signature).decode(),
'filename': os.path.basename(filename)
}
# 转换为 JSON 格式
data_packet_json = json.dumps(data_packet)
# 建立网络连接并发送数据
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((receiver_ip, receiver_port))
s.sendall(data_packet_json.encode('utf-8'))
print("文件已发送!")
if __name__ == "__main__":
# 加载密钥
receiver_public_key = load_key('receiver_public.pem')
sender_private_key = load_key('sender_private.pem')
# 文件路径和接收方信息
filename = '1.txt'
receiver_ip = '192.168.98.130' # 替换为接收方的IP地址
receiver_port = 12345
send_file(filename, receiver_ip, receiver_port, receiver_public_key, sender_private_key)

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAvLvy6YiIfvCz+aF9gEkfHREjPPSPG6jI/hhSTiGG9i71rnCC
rHFB3Nk0A1i/tv3rVn70O9W+jKroUNDNQaAoI3ytv0r+3iw/qS8S53ErGEV5Ms7Y
MmgAkFTmQArWx9muD9JvLo1XFXvQFSIgtthdyqXC+SKnWsK9b/gXN7qVv/r5sR5A
Mn067QZhVEc4cNfF0UEBS2+8UgxhH3PqbZzfV+cBfKBQ8JNWVgDmRSvKowQOQE87
tMwTgsQKONuYFHtnzQ1Lo8gyF0f8PVRfln+hoj9WjvvCg0C9wBbfIuAxCgkqKEbb
48KgUiNmT1YFJ3PaPAYjjchqQeFCT5CPqdC6jQIDAQABAoIBAARvgCKlXFxPX+DH
IprUjuH4OHjmfLWh7MA8AopKM20g2IP2HBFrpxoqTDEVRt+6wxXQNKvkNsQ5yAm4
2voRai5NGrdbFdrFEayc4tQu+VwVVecwAUqFFsOi8H5b7YUv/SYkRCg2z++SbnVG
Bg5bXTALJpfncF4deKXVPFvJYMzspttNyE9lvoDL090/QsfITnOC6MNwu5EWwoH5
zTJxxraiJpPnUiSA2S7w+EQV+WHgUCY2MFt4c1jIKfjtqB7g9wYQouKkVS3RzZoq
iXqTS+avj5iMT+VRgxV5+WoRr+JXJf9aRmPtKqlFO4Jxt49EGLooBmw3Eq3WCItL
gMUx1oECgYEAvy0anPGVLkDA1kRNsUCchKCnh2J4vWf8IZbS8OWSQm03Pyx26cUv
AgeVtYXNqcCBP5f4X1Jg+jtwm7GwVQfD8CoMIoS0RKrEldFF9K03XfxI7mD+fjBo
xAmcT1XHniMsAh6gT0bc7OAzt8wT7/e/cRSe/uBnSxROvCl7bezfgZECgYEA/Lre
NlsyDEAuKgB/FRGnJDBWIlCULHLRfOi4dJi452JvgvWvxEa1DG2Hptbt+EfWuHIs
Lf6hz+ePQLG022S8/KetkLwSqhohsOOhXoAuxf8j8ETUrMPHsaKUTjJNB6/0L1dt
rKOxc0oQRuN0uH/f/uwbcKaOZ2Iypm5k+btTqz0CgYEArsSE98TCJC5+G2MFw2zV
qUlU3adfyYcuL2a6IA8+zgsZ3l6/tqXUe36DlhZkFTMu9PvwyvN8REXig/LEyHb4
4K0Put6mDcAvRuaxlSRk4T6pTYLOJH4MyGogw0Yf3qk4qhdlZhPaE5JCtVuTPmS2
VqILV+W9iB1gfRNPCwborIECgYAIO7I3hRsJSSH33lJFhnCyfhygO43IMOlgL1iq
+7qyVwOY+ZYDR+ZoBD1yEvhnqTd2hMmpqeztj/abve5NY2fAt1mxKF9XSUilsZS1
NmnPq3MpRaTECBC+WbSJI5xczr+etzNsd1y1i8kh9hD8XbYXYOu37MUg2xMZVulV
NWQRZQKBgASHsgW9kFtsNKqfvjFwCQlFF1o21kRcoUgmF1tFkhBxzWGUpeNJCLN5
Y9eG9AY0FzlSG7ZfcMlSo0vZ5UZIciAx1Cyo943ArJSwo09DK7kVh2Hzo6lHMStg
LP6/py2oIITlOfIx/x336EpKlDIpijKbhhxEHEfTnCra24f9hytP
-----END RSA PRIVATE KEY-----

@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvLvy6YiIfvCz+aF9gEkf
HREjPPSPG6jI/hhSTiGG9i71rnCCrHFB3Nk0A1i/tv3rVn70O9W+jKroUNDNQaAo
I3ytv0r+3iw/qS8S53ErGEV5Ms7YMmgAkFTmQArWx9muD9JvLo1XFXvQFSIgtthd
yqXC+SKnWsK9b/gXN7qVv/r5sR5AMn067QZhVEc4cNfF0UEBS2+8UgxhH3PqbZzf
V+cBfKBQ8JNWVgDmRSvKowQOQE87tMwTgsQKONuYFHtnzQ1Lo8gyF0f8PVRfln+h
oj9WjvvCg0C9wBbfIuAxCgkqKEbb48KgUiNmT1YFJ3PaPAYjjchqQeFCT5CPqdC6
jQIDAQAB
-----END PUBLIC KEY-----

@ -0,0 +1,42 @@
import os
import json
from utils import aes_encrypt, rsa_encrypt, generate_signature, load_key
import base64
def send_file(filename, receiver_public_key, sender_private_key):
# 读取文件内容
with open(filename, 'rb') as f:
file_data = f.read()
# 生成随机AES密钥
aes_key = os.urandom(16)
# 加密文件
nonce, ciphertext, tag = aes_encrypt(file_data, aes_key)
# 使用接收方公钥加密AES密钥
encrypted_aes_key = rsa_encrypt(aes_key, receiver_public_key)
# 生成数字签名(针对原始文件内容)
signature = generate_signature(sender_private_key, file_data)
# 封装数据包
data_packet = {
'nonce': base64.b64encode(nonce).decode(),
'ciphertext': base64.b64encode(ciphertext).decode(),
'tag': base64.b64encode(tag).decode(),
'encrypted_key': base64.b64encode(encrypted_aes_key).decode(),
'signature': base64.b64encode(signature).decode(),
'filename': os.path.basename(filename)
}
# 保存数据包到文件
with open('data_packet.json', 'w') as f:
json.dump(data_packet, f)
print("文件已加密并发送。")
if __name__ == "__main__":
receiver_public_key = load_key('receiver_public.pem')
sender_private_key = load_key('sender_private.pem')
send_file('1.txt', receiver_public_key, sender_private_key)

158
ui.py

@ -0,0 +1,158 @@
import tkinter as tk
from tkinter import filedialog, messagebox
import os
import subprocess
from sender import send_file
from receiver import receive_file
from utils import load_key
class FileTransferApp:
def __init__(self, root):
self.root = root
self.root.title("文件传输系统")
self.root.geometry("800x900") # 增大窗口尺寸
self.root.resizable(False, False) # 禁止调整窗口大小
# 设置窗口背景色
self.root.configure(bg="#f5f5f5")
# 加载密钥
self.sender_private_key = load_key('sender_private.pem')
self.receiver_public_key = load_key('receiver_public.pem')
self.receiver_private_key = load_key('receiver_private.pem')
self.sender_public_key = load_key('sender_public.pem')
# 创建UI
self.create_main_frame()
def create_main_frame(self):
# 主界面,选择发送方或接收方
self.main_frame = tk.Frame(self.root, bg="#f5f5f5")
self.main_frame.pack(fill="both", expand=True)
self.selection_var = tk.StringVar(value="sender") # 默认选择发送方
# 选择发送方或接收方
tk.Radiobutton(self.main_frame, text="我是发送方", variable=self.selection_var, value="sender", font=("Arial", 16),
bg="#f5f5f5", command=self.switch_mode).pack(pady=20)
tk.Radiobutton(self.main_frame, text="我是接收方", variable=self.selection_var, value="receiver", font=("Arial", 16),
bg="#f5f5f5", command=self.switch_mode).pack(pady=20)
# 按钮:生成密钥
tk.Button(self.main_frame, text="生成公钥/私钥对", font=("Arial", 16), bg="#8BC34A", fg="white", relief="raised", bd=4,
width=20, height=2, command=self.generate_keys).pack(pady=20)
# 初始显示发送方界面
self.sender_frame = None
self.receiver_frame = None
self.switch_mode()
def switch_mode(self):
"""切换模式(发送方或接收方)"""
# 清空当前界面
if self.sender_frame:
self.sender_frame.destroy()
if self.receiver_frame:
self.receiver_frame.destroy()
mode = self.selection_var.get()
if mode == "sender":
self.create_sender_frame()
elif mode == "receiver":
self.create_receiver_frame()
def create_sender_frame(self):
"""创建发送方界面"""
self.sender_frame = tk.LabelFrame(self.main_frame, text="发送文件", padx=30, pady=30, bg="#ffffff", font=("Arial", 14, "bold"))
self.sender_frame.pack(padx=30, pady=30, fill="both", expand=True)
self.filename_var = tk.StringVar()
# 选择文件按钮
tk.Button(self.sender_frame, text="选择文件", command=self.select_file,
font=("Arial", 16), bg="#4CAF50", fg="white", relief="raised", bd=4,
width=20, height=3, activebackground="#45a049").pack(padx=10, pady=15)
# 显示文件路径
self.filename_entry = tk.Entry(self.sender_frame, textvariable=self.filename_var, width=60, font=("Arial", 14), state='readonly', bd=3)
self.filename_entry.pack(padx=10, pady=15)
# 输入接收方 IP 和端口
tk.Label(self.sender_frame, text="接收方 IP:", font=("Arial", 14), bg="#ffffff").pack(pady=10)
self.receiver_ip_entry = tk.Entry(self.sender_frame, width=40, font=("Arial", 14), bd=3)
self.receiver_ip_entry.pack(pady=10)
self.receiver_ip_entry.insert(0, "192.168.1.1")
tk.Label(self.sender_frame, text="接收方端口:", font=("Arial", 14), bg="#ffffff").pack(pady=10)
self.receiver_port_entry = tk.Entry(self.sender_frame, width=40, font=("Arial", 14), bd=3)
self.receiver_port_entry.pack(pady=10)
self.receiver_port_entry.insert(0, "12345")
# 增大按钮大小
send_button = tk.Button(self.sender_frame, text="发送文件", command=self.send_file,
font=("Arial", 16), bg="#007BFF", fg="white", relief="raised", bd=4,
width=25, height=3, activebackground="#0056b3")
send_button.pack(padx=10, pady=30, fill='x')
def create_receiver_frame(self):
"""创建接收方界面"""
self.receiver_frame = tk.LabelFrame(self.main_frame, text="接收文件", padx=30, pady=30, bg="#ffffff", font=("Arial", 14, "bold"))
self.receiver_frame.pack(padx=30, pady=30, fill="both", expand=True)
# 接收文件按钮
receive_button = tk.Button(self.receiver_frame, text="接收文件", command=self.receive_file,
font=("Arial", 16), bg="#FF5722", fg="white", relief="raised", bd=4,
width=25, height=3, activebackground="#e64a19")
receive_button.pack(padx=10, pady=30, fill='x')
def generate_keys(self):
"""调用 generate_key.py 生成公钥和私钥"""
try:
# 使用 subprocess 调用 generate_key.py 生成密钥对
subprocess.run(["python", "generate_key.py"], check=True)
messagebox.showinfo("成功", "公钥和私钥已生成!")
except subprocess.CalledProcessError as e:
messagebox.showerror("错误", f"密钥生成失败:{e}")
def select_file(self):
"""选择文件"""
file_path = filedialog.askopenfilename()
if file_path:
self.filename_var.set(file_path)
def send_file(self):
"""发送文件"""
filename = self.filename_var.get()
if not filename or not os.path.exists(filename):
messagebox.showerror("错误", "请选择有效的文件!")
return
receiver_ip = self.receiver_ip_entry.get()
receiver_port = self.receiver_port_entry.get()
if not receiver_ip or not receiver_port:
messagebox.showerror("错误", "请填写接收方的 IP 和端口!")
return
try:
# 调用 sender.py 中的 send_file 函数
send_file(filename, receiver_ip, int(receiver_port), self.receiver_public_key, self.sender_private_key)
messagebox.showinfo("成功", "文件发送成功!")
except Exception as e:
messagebox.showerror("错误", f"文件发送失败:{e}")
def receive_file(self):
"""接收文件"""
try:
port = 12345
# 调用 receiver.py 中的 receive_file 函数
receive_file(port, self.receiver_private_key, self.sender_public_key)
messagebox.showinfo("成功", "文件接收成功!")
except Exception as e:
messagebox.showerror("错误", f"文件接收失败:{e}")
if __name__ == "__main__":
root = tk.Tk()
app = FileTransferApp(root)
root.mainloop()

@ -0,0 +1,70 @@
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP, AES
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
import base64
import os
# 生成RSA密钥对
def generate_rsa_keypair():
key = RSA.generate(2048)
private_key = key.export_key()
public_key = key.publickey().export_key()
return private_key, public_key
# 保存密钥到文件
def save_key(filename, key):
with open(filename, 'wb') as f:
f.write(key)
# 加载密钥
def load_key(filename):
with open(filename, 'rb') as f:
return f.read()
# AES加密文件内容
def aes_encrypt(data, key):
cipher = AES.new(key, AES.MODE_EAX)
ciphertext, tag = cipher.encrypt_and_digest(data)
return cipher.nonce, ciphertext, tag
# AES解密文件内容
def aes_decrypt(nonce, ciphertext, tag, key):
cipher = AES.new(key, AES.MODE_EAX, nonce=nonce)
return cipher.decrypt_and_verify(ciphertext, tag)
# 使用RSA加密对称密钥
def rsa_encrypt(data, public_key):
cipher = PKCS1_OAEP.new(RSA.import_key(public_key))
return cipher.encrypt(data)
# 使用RSA解密对称密钥
def rsa_decrypt(data, private_key):
cipher = PKCS1_OAEP.new(RSA.import_key(private_key))
return cipher.decrypt(data)
# 生成数字签名
def generate_signature(private_key, data):
key = RSA.import_key(private_key)
h = SHA256.new(data)
signature = pkcs1_15.new(key).sign(h)
return signature
# 验证数字签名
def verify_signature(public_key, data, signature):
key = RSA.import_key(public_key)
h = SHA256.new(data)
try:
pkcs1_15.new(key).verify(h, signature)
return True
except (ValueError, TypeError):
return False
Loading…
Cancel
Save