代写代考 ICS 32 students :) ) have been raising concerns over the poor security and

Assignment 5: Encrypted Graphical User Interface Introduction
So we have finally arrived at the end. Over the course of the last four assignments you have built, from the ground up, a feature rich program in Python. The code that you have written enables a person to write personal journal entries, publish those entries to an online server, and enrich them with data from web API’s. Now it’s time to bring all of these features together by moving them from the command line to the windowed world of the graphical user interface.
For the past two months, partnering organizations (e.g., ICS 32 students 🙂 ) have been raising concerns over the poor security and privacy of the ICS 32 Distributed Social platform. In response to the concerns raised by its partners, the ICS32 Distributed Social organization (e.g., ICS 32 instructors) has implemented a new authentication scheme. Rather than rely on a user name and password, users will now be required to supply an ed25519 public-key with each message. Additionally, all messages sent to the server must first be encrypted with the DSP server’s public key.
So for this assignment you will need to update your program to support the new authentication process for the DSP server and integrate your existing code into a new graphical interface using the Tkinter graphical toolkit.

Copyright By PowCoder代写 加微信 powcoder

This will be your second pair assignment. You are allowed to work on this assignment with at least 1 other student. Canvas groups have been created for you. If you plan on working with a partner you both MUST join a Canvas group. Once you have joined a group the leader will be responsible for assignment submission, so only one person in your group will submit.
Summary of Program Requirements
Subclass the Profile class in your DS program to support encryption and public key authentication. Read and understand documentation for a 3rd party library.
Update your DS program to communicate with the new DS Server.
Modify and extend the ICS 32 DS Demo Tkinter interface.
Integrate existing code with Tkinter widgets.
Modify and update Tkinter widgets to display program information to a user.
Learning Goals
Use inheritance to extend class functionality
Install and use 3rd party libraries
Learn how to build basic Graphical User Interfaces with Tkinter and Python. Write event handlers and callback functions.
Structure and organize a GUI program with classes.
Program Requirements Part 1
The ICS32 Distributed Social organization has decided to implement the NaCl networking and encryption library to help strengthen the security of its social messaging platform. Rather than implement the NaCl specification directly, the DS org will use a 3rd party library that is already written in Python called PyNaCl. The PyNaCl library supports the use of public key encryption using public and private keys. The following diagram depicts the basic process for using public and private keys to encrypt and decrypt data.
You can think of the role of public and private keys in public key encryption like a username and password. While it is safe to share a public key (username), you would never want to share a private key (password). When both public and private keys are combined, the public key encryption algorithm will use them to encrypt data into a format that can only be decrypted with the same public and private keys. This is the method you will use to add encryption to all posts entries and bio stored in your program’s dsu file.
 Contents
Introduction
Summary of Program Requirements Learning Goals
Program Requirements Part 1
Installing the PyNaCl Package Prepare your Environment Adding Support for Encryption Encrypted Server Communication
Additional Considerations
Extra Credit
Submitting
Starter Project
How we will grade your submission

However, since we still want our messages to be readable from the DS website, we will also need to add support for encrypting our post information using a key that the DS server can use to decrypt messages. Fortunately, this process is nearly identical to what you will use for local encryption to your dsu file. The following diagram depicts the basic process for using public and private keys to share encrypted data.
Rather than encrypt a message using a public key that we create, we encrypt using the public key of the source where we want to share our message. This means that we need a way to exchange public keys with the DS server. To keep things as consistent as possible, the DS organization has modified the token key used by its protocol to store the public encryption keys exchanged between client programs and the server. But more on this change a little bit later.
For Part 1, you will create the following new modules:
1. NaClDSEncoder.py: A helper module provided for you, complete.
2. NaClProfile.py: A template class provided for you, incomplete.
To prepare your ICS32 DS program for network communication using NaCl, there are a number of tasks you must complete. They have
been divided into individual parts below to help you prioritize your program requirements.
Installing the PyNaCl Package
The first thing you will need to do is install the PyNaCl package to your instance of Python:
pip install pynacl
If all goes well, you should see a message that is similar to “Successfully installed pynacl-1.4.0”. To verify that the package was installed, open up your Python shell and type:
If you receive any response other than a new line of input, it’s likely that pip installed the package to a different version of Python. Check your messages and make sure that you are testing the package in the same instance of the Python shell as where you installed the package.
Prepare your Environment
Thankfully, the DSP org has released the NaClDSEncoder module (provided for you in the starter repository) to abstract away some of the steps required to interact with their new encrypted platform. So the next thing you will want to do is download the module and test it.
A simple test is included in the following snippet, you are free to use it to validate that your environment is properly configured. You may also find the use of the NaClDSEncoder class in the test class a useful reference for your assignment code.
Print to PDF
>>> import nacl >>>

If you have everything set up properly, you should see some output that will look similar to the following (NOTE: your values will be different every time you run the generate() function!):
Adding Support for Encryption
Next, you will need to write a new class to handle the new encryption policies required by the DSP org. Since the DSP server will now expect your program to authenticate with a public key and send posts that have been encrypted using the DSP public key, you are going to need to rethink the way your current program works. Fortunately, the Profile module that you have been using in your DSP program, is still quite useful. Therefore, the best course of action is probably to subclass the Profile class. To help you with this task, you will use the following skeleton to get started (also included in the starter repository):
keypair: ziq0wkuDE0n0i+SFBtTEE1w9y/gG9C19NuAE8b8d/Qo=8ldBMVgC8QkOPl9nBKikIc+fLxUCuadqfAOXl90MoiA=
public key: ziq0wkuDE0n0i+SFBtTEE1w9y/gG9C19NuAE8b8d/Qo=
private key: 8ldBMVgC8QkOPl9nBKikIc+fLxUCuadqfAOXl90MoiA=
———————————————————————-
Ran 3 tests in 0.001s OK
# NaClDSEncoder_test.py
# Simple test harness for the NaClDSEncoder class
# . Baldwin
import unittest
from NaClDSEncoder import NaClDSEncoder
from nacl.public import PrivateKey, PublicKey, Box
class TestNaClDSEncoder(unittest.TestCase):
def test_generate(self):
# create an NaClDSEncoder object nacl_enc = NaClDSEncoder()
# generate new keys nacl_enc.generate()
# typically in a unittest printing this way is unnecessary
# including here for demonstration purposes…
# use print to display the keys, notice how the keypair is
# just the public and private keys combined.
print(‘\n’)
print(f’keypair: {nacl_enc.keypair}’) print(f’public key: {nacl_enc.public_key}’) print(f’private key: {nacl_enc.private_key}’)
self.assertEqual(len(nacl_enc.keypair), 88)
self.assertEqual(nacl_enc.public_key, nacl_enc.keypair[:44])
self.assertEqual(nacl_enc.private_key, nacl_enc.keypair[44:])
def test_encode_public(self):
# Use the NaClDSEncoder to create new keys test_keys = NaClDSEncoder() test_keys.generate()
# Test the NaClDSEncoder using the test_keys
nacl_enc = NaClDSEncoder()
pkey = nacl_enc.encode_public_key(test_keys.public_key)
self.assertEqual(type(pkey), PublicKey)
def test_encode_private(self):
# Use the NaClDSEncoder to create new keys test_keys = NaClDSEncoder() test_keys.generate()
# Test the NaClDSEncoder using the test_keys
nacl_enc = NaClDSEncoder()
prvkey = nacl_enc.encode_private_key(test_keys.private_key)
self.assertEqual(type(prvkey), PrivateKey)
if __name__ == ‘__main__’: unittest.main()

Since we will be required to send encrypted messages to the new DSP server, we might as well add support for local encryption as well to prevent unwanted parties from reading our journal entries. Therefore, in the NaClProfile class you will extend the Profile module to not only encrypt messages that will be sent to the DSP server, but also messages stored in the .dsu file.
The comments in the skeleton code will provide you with some guidance on what you need to do. In addition to the incomplete methods, you will also need to override two methods from the Profile class. If done correctly, all of your new data attributes as well as your encrypted messages will be saved to the .dsu file passed to the save_profile method, without having to change anything else!
# TODO: Install the pynacl library so that the following modules are available # to your program.
import nacl.utils
from nacl.public import PrivateKey, PublicKey, Box
# TODO: Import the Profile and Post classes
# TODO: Import the NaClDSEncoder module
# TODO: Subclass the Profile class
class NaClProfile:
def __init__(self):
TODO: Complete the initializer method. Your initializer should create the follow three
public data attributes:
public_key:str
private_key:str
keypair:str
Whether you include them in your parameter list is up to you. Your decision will frame how you expect your class to be used though, so think it through.
def generate_keypair(self) -> str: “””
Generates a new public encryption key using NaClDSEncoder.
TODO: Complete the generate_keypair method.
This method should use the NaClDSEncoder module to generate a new keypair and populate
the public data attributes created in the initializer.
:return: str “””
def import_keypair(self, keypair: str): “””
Imports an existing keypair. Useful when keeping encryption keys in a location other than the
dsu file created by this class.
TODO: Complete the import_keypair method.
This method should use the keypair parameter to populate the public data attributes created by
the initializer.
NOTE: you can determine how to split a keypair by comparing the associated data attributes generated by the NaClDSEncoder
TODO: Override the add_post method to encrypt post entries.
Before a post is added to the profile, it should be encrypted. Remember to take advantage of the
code that is already written in the parent class.
NOTE: To call the method you are overriding as it exists in the parent class, you can use the built-in super keyword:
super().add_post(…)
TODO: Override the get_posts method to decrypt post entries.
Since posts will be encrypted when the add_post method is used, you will need to ensure they are
decrypted before returning them to the calling code.
:return: Post
NOTE: To call the method you are overriding as it exists in the parent class you can use the built-in super keyword:
super().get_posts()
TODO: Override the load_profile method to add support for storing a keypair.
Since the DS Server is now making use of encryption keys rather than username/password attributes, you will
need to add support for storing a keypair in a dsu file. The best way to do this is to override the
load_profile module and add any new attributes you wish to support.
NOTE: The Profile class implementation of load_profile contains everything you need to complete this TODO. Just add
support for your new attributes.
def encrypt_entry(self, entry:str, public_key:str) -> bytes: “””
Used to encrypt messages using a 3rd party public key, such as the one that
the DS server provides.
TODO: Complete the encrypt_entry method.
NOTE: A good design approach might be to create private encrypt and decrypt methods that your add_post,
get_posts, and this method can call.
:return: bytes “””

To learn how to encrypt and decrypt information using a keypair, you will need to consult the documentation for the module. The main page for the docs is a good place to start if you want to learn more about PyNaCl. However, since you are only required to implement a small portion of the overall PyNaCl module, you may find the examples on the Public Key Encryption page to be the most helpful. Feel free to discuss your findings on Zulip with your classmates.
Once your new Profile subclass has been completed, you can validate it by running the following program:
from Profile import Profile, Post from NaClProfile import NaClProfile
np = NaClProfile()
kp = np.generate_keypair()
print(np.public_key)
print(np.private_key)
print(np.keypair)
# Test encryption with 3rd party public key
ds_pubkey = “jIqYIh2EDibk84rTp0yJcghTPxMWjtrt5NW4yPZk3Cw=”
ee = np.encrypt_entry(“Encrypted Message for DS Server”, ds_pubkey)
# Add a post to the profile and check that it is decrypted.
np.add_post(Post(“Hello Salted World!”))
p_list = np.get_posts()
print(p_list[0].get_entry())
# Save the profile
np.save_profile(PATH/TO/DSU)
print(“Open DSU file to check if message is encrypted.”)
input(“Press Enter to Continue”)
# Create a new NaClProfile object and load the dsu file.
np2 = NaClProfile() np2.load_profile(PATH/TO/DSU) # Import the keys np2.import_keypair(kp)
# Verify the post decrypts properly
p_list = np2.get_posts()
print(p_list[0].get_entry())
Just remember that once post entries have been encrypted with a keypair, they can only be decrypted with the same keypair! Encrypted Server Communication
Finally, you will need to make sure your new authentication and encryption interface works with the updated DSP Server. To support keypair encryption, a few changes have been made to the way the DSP Server handles messages.
You might recall from previous assignments, the token key was not used during join requests with the DS server. With the new public key encryption in place, you must now perform a join request using a public key that you have generated locally. The DS server will then use this public key to decrypt all of the messages that you send moving forward.
You will also need to slightly adjust the way in which you use the token value that you receive from the DS Server. Under the rules of the non-encrypted DS server you were required to send the token you received from the server in all of your messages. Now, rather than send back the server token, you will send your public key as the value of the token key.
The token key in DS Protocol messages should be used to store the value of your public encryption key.
Finally, the only thing we are missing is a public key from the DS server. When you successfully join the server your response will now contain the public key used by the server to decrypt your messages:
{“response”: {“type”: “ok”, “message”: “”, “token”:”server_public_key”}}
So rather than return this response token to the server like you did in previous assignments, you will now need to store this value in your program somewhere and use it to encrypt your messages before sending. The encrypted_entry function that is part of the NaClProfile skeleton class is designed to support this requirement.
If you have implemented your NaClProfile class and modified your communication with the DS Server successfully, your program should continue to work as expected, just a little more secure.
Once you have encryption in place, it’s time to wire everything up to a graphical user interface. For this part of the assignment you will be given a mostly functional Tkinter program to get you started. Learning graphical toolkits is a big undertaking that is typically filled with a lot of trial and error. We could spend an entire quarter mastering the Tkinter toolkit if we so desired. So, rather than get bogged down attempting to work through all of the nuances of getting a Tkinter GUI to function the way we want, you will be spending your remaining time in this class extending an existing program that already works pretty well. The following image depicts the ICS 32 DS program in it’s default state with a DSU file loaded.
# join as existing or new user
{“join”: {“username”: “ohhimark”,”password”: “password123″,”token”:”my_public_key”}}

However, the version that is available for you, does not yet have the features required to get to the state pictured. To make this program fully functional, you will have to start with the template (included in the starter repository) and complete all of the TODO items described in the code comments.
For Part 2, you will complete the following new modules: 1. a5.py: A GUI module provided for you, incomplete.
The following section is optional. You are free to jump into the a5.py code and start working on the TODO items any way you want. However, there is a lot to do for this assignment, so to mitigate some of the complexity we are providing some additional notes on how to go about completing the TODO items for this part of the assignment.
A5 Code Walkthrough
We strongly encourage you to take a pass at the starter code on your own first. Try and complete each TODO without using the notes included here. But if you get stuck, feel free to come here for further guidance.
The line number references here might be off by 1 or 2, but should still generally take you to the associated section of the starter code. Of course, as you edit the file, the line numbers will continue to fall out of sync, so you might find it useful to keep a reference copy of the original starter code.
TODO: Line 271
Let’s start with the online_clicked callback. (all line numbers are from unmodified starter code file) self.footer = Footer(self.root, save_callback=self.save_profile)
The goal here is to update the Footer initializer to support a callback for the online checkbox widget. The solution is to replicate the existing save_callback functionality:
1. Add a new parameter to Footer (…) after save_callback, using the same conventions as save_callback. Check line 119, see the statement save_callback=None? Add another parameter called online_callback.
2. Now we need to do something with that new parameter. So check line 122, see how the value of the save_callback parameter is assigned to a private attribute called self.savecallback? Replicate that for online_callback. Notice, we already have a method we can use called online_click. The only difference, however, is that the online_changed method in MainApp has a parameter: value:bool. So we also need to pass a parameter when we call the callback. Fortunately the parameter already exists for us and can be found in the initializer for footer.
3. Next, we need to add code to online_click, line 137. Remove the ‘pass’ keyword, and reproduce the code used in save_click, but change yo

程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com