We’re going to create a Drafter user interface for this application as well. We have already provided some code and tests for you, to help you get started.
You will need to implement three functions:
index which consumes the current State and produces the actual Page content, including the current status message, two input boxes, and two buttons.encrypt which consumes the current State and a new message, updates the State’s fields with the encrypted text and hash, and returns the index page’s content.decrypt which consumes the current State, a new message and a latest_hash, updates the State’s fields with the decrypted text, and returns the index page’s content.The encrypt_text, decrypt_text, and hash_text functions are provided to you from the crypto_tools library. They should work the same way as the functions you implemented.
The State has the fields message, latest_hash, and status. Read over their documentation closely to see what they represent, and how you should use them.
Tips:
index function needs to have Page content; the encrypt and decrypt routes can reuse the index function.from drafter import *
from crypto_tools import encrypt_text, decrypt_text, hash_text
from dataclasses import dataclass
from bakery import assert_equal
ROTATION = 4
BASE = 31
HASH_SIZE = 10**9
@dataclass
class State:
"""
The current state of the Crypto Corgi application.
Attributes:
message (str): The latest saved encrypted or decrypted text. After
encrypting, this should be set to the encrypted text. After
decrypting, this should be set to the decrypted text (but only if
it was decrypted successfully).
latest_hash (str): The latest saved hash. After encrypting, this should be
set to the hash of the original message. After decrypting, this should
be unchanged.
status (str): A string message to display to the user, with information
about the latest encryption and decryption attempt.
"""
message: str
latest_hash: str
status: str
@route
def index(state: State):
pass
@route
def encrypt(state: State, given_message: str):
pass
@route
def decrypt(state: State, given_message: str, latest_hash: str):
pass
# Initial version of index page
assert_equal(index(State("", "", "Write your message below")),
Page(State("", "", "Write your message below"), [
Header("Crypto Corgi"),
"Write your message below",
"Message:",
TextBox("given_message", ""),
Button("Encrypt", "encrypt"),
"Hash:",
TextBox("latest_hash", ""),
Button("Decrypt", "decrypt"),
]))
# Loading index with content
assert_equal(index(State("Test", "1000", "Write your message below")),
Page(State("Test", "1000", "Write your message below"), [
Header("Crypto Corgi"),
"Write your message below",
"Message:", TextBox("given_message", "Test"),
Button("Encrypt", "encrypt"),
"Hash:", TextBox("latest_hash", "1000"),
Button("Decrypt", "decrypt"),
]))
# Encrypt a message
assert_equal(
encrypt(State("", "", ""), "Hello world!"),
Page(
State("Lipps$~{svph%~", "533815340", "Message encrypted and hashed!"),
[
Header("Crypto Corgi"),
"Message encrypted and hashed!",
"Message:",
TextBox("given_message", "Lipps$~{svph%~"),
Button("Encrypt", "encrypt"),
"Hash:",
TextBox("latest_hash", "533815340"),
Button("Decrypt", "decrypt"),
],
),
)
# Successful decryption
assert_equal(
decrypt(State("", "", ""), "Lipps$~{svph%~", "533815340"),
Page(
State("Hello world!", "", "Message decrypted successfully!"),
[
Header("Crypto Corgi"),
"Message decrypted successfully!",
"Message:",
TextBox("given_message", "Hello world!"),
Button("Encrypt", "encrypt"),
"Hash:",
TextBox("latest_hash", ""),
Button("Decrypt", "decrypt"),
],
),
)
# Unsuccessful decryption
assert_equal(
decrypt(State("The original message", "", ""), "Hello world!", "533815340"),
Page(State("The original message", "", "Decryption failed: Hash mismatch!"), [
Header("Crypto Corgi"),
"Decryption failed: Hash mismatch!",
"Message:",
TextBox("given_message", "The original message"),
Button("Encrypt", "encrypt"),
"Hash:",
TextBox("latest_hash", ""),
Button("Decrypt", "decrypt"),
]),
)
# Comment out this line to skip running the actual server.
start_server(State("", "", ""))
Drafter is not installed on Dodona, so there is no exercise to submit here: this page is for reading and studying the code, not for running it.