Commit d732d9af authored by Shashank Kumar's avatar Shashank Kumar

Adding Encryption Tutorials

Tutorial Parser added which can be used to parse JSON and return
a Widget tree for UI
Encryption 101 tutorial added
parent 258044b5
[
{"application_settings": 1},
{"blog": 1},
{"cli": 1},
{"communication": 1},
{"application_settings": []},
{"blog": []},
{"cli": []},
{"communication": []},
{"encryption":[
{
"tutorials": 0
"tutorials": [
{
"Encryption 101": {
"difficulty": "Beginner"
}
}
]
},
{
"tools": [
......@@ -27,9 +33,9 @@
}
]
},
{"how_to_use": 1},
{"profile_settings": 1},
{"theme_settings": 1},
{"vcs": 1},
{"way_ahead": 1}
{"how_to_use": []},
{"profile_settings": []},
{"theme_settings": []},
{"vcs": []},
{"way_ahead": []}
]
'''
Modules containing Encryption classes
'''
from copy import copy as cp
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
......@@ -37,7 +35,7 @@ class Encryption(BoxLayout):
self.ids[option_to_enable + '_box'].canvas.before.children[0].rgba = [1, 1, 1, 1]
self.ids[option_to_enable].color = (0, 0, 0, 1)
all_options_items_copy = cp(self.all_options_items)
all_options_items_copy = self.all_options_items[:]
all_options_items_copy.remove(option_to_enable)
for option in all_options_items_copy:
......
......@@ -66,7 +66,7 @@ class DecryptAMessage(BoxLayout):
key_column_box = KeyColumnBox()
key_box = DecryptKeyBox()
key_box.ids['Key_button'].id = fingerprint
key_box.ids['Key_button'].id = fingerprint # pylint: disable=invalid-name
key_box.ids['Key_button'].bind(
on_press=self.decrypt_message_popup
)
......
......@@ -73,14 +73,14 @@ class DisplayAndManageKeyPair(BoxLayout):
key_info_label = KeyInfoLabel(text=fingerprint_text)
key_column_box.add_widget(key_info_label)
key_box = KeyBox()
key_box.ids['Key_button'].id = fingerprint
key_box.ids['Key_button'].id = fingerprint # pylint: disable=invalid-name
key_box.ids['Key_button'].bind(
on_press=self.display_public_key
)
key_column_box.add_widget(key_box)
if fingerprint in all_private_keys.keys():
key_box = KeyBox()
key_box.ids['Key_button'].id = fingerprint
key_box.ids['Key_button'].id = fingerprint # pylint: disable=invalid-name
key_box.ids['Key_button'].bind(
on_press=self.display_private_key
)
......
......@@ -63,7 +63,7 @@ class EncryptAMessage(BoxLayout):
key_column_box = KeyColumnBox()
key_box = EncryptKeyBox()
key_box.ids['Key_button'].id = fingerprint
key_box.ids['Key_button'].id = fingerprint # pylint: disable=invalid-name
key_box.ids['Key_button'].bind(
on_press=self.encrypt_message_popup
)
......
......@@ -38,8 +38,7 @@ def create_key_pair(name, email, comment, expire_date, passphrase=''):
key = gpg.gen_key(input_data)
if key.fingerprint:
return key.fingerprint
else:
raise GPGError(message=getattr(key, 'stderr'))
raise GPGError(message=getattr(key, 'stderr'))
def list_all_keys():
......@@ -73,8 +72,7 @@ def encrypt_message(keyid, message):
encrypted_message_object = gpg.encrypt(message, keyid)
if encrypted_message_object.ok:
return str(encrypted_message_object)
else:
raise GPGError(message=encrypted_message_object.status)
raise GPGError(message=encrypted_message_object.status)
def decrypt_message(message, passphrase):
......@@ -85,5 +83,4 @@ def decrypt_message(message, passphrase):
decrypted_message_object = gpg.decrypt(message, passphrase=passphrase)
if decrypted_message_object.ok:
return str(decrypted_message_object)
else:
raise GPGError(message=decrypted_message_object.status)
raise GPGError(message=decrypted_message_object.status)
......@@ -64,7 +64,7 @@ class Tools(BoxLayout):
tool_color = difficulty_palette[tool_difficulty]
tool_box_widget = ToolBox()
tool_box_widget.ids['tool_button'].bind(on_press=self.open_tool)
tool_box_widget.id = key
tool_box_widget.id = key # pylint: disable=invalid-name
tool_box_widget.canvas.before.children[0].rgba = tool_color
tool_box_widget.ids['tool_box_title'].text = tool_title
tool_box_widget.ids['tool_box_difficulty'].text = tool_difficulty
......@@ -93,7 +93,7 @@ class Tools(BoxLayout):
self.remove_widget(self.children[0])
box_layout = BoxLayout()
box_layout.id = 'tools_menu'
box_layout.id = 'tools_menu' # pylint: disable=invalid-name
box_layout.orientation = 'vertical'
back_to_tool_menu = BackToToolsMenu()
......@@ -106,7 +106,7 @@ class Tools(BoxLayout):
def back_to_tools_menu(self, button_object):
'''
back_to_tools_menu removed the tool widget and replaces tools menu
back_to_tools_menu removes the tool widget and replaces tools menu
'''
self.remove_widget(button_object)
self.remove_widget(self.children[0])
......
[
{
"content": [
{
"type": "image",
"url": "http://www.bigfoto.com/lines-image.jpg"
},
{
"type": "text",
"text": "Welcome to Encryption 101. This is just to get you started with what the term 'Encryption' means and how it is practiced in real life. Roughly speaking, encryption is the problem of how two parties can communicate in secret in the presence of an eavesdropper. The main goals of this chapter are to develop a meaningful and useful definition of what we are trying to achieve, and to take some first steps in actually achieving it. "
},
{
"type": "question",
"question": "So, what can you secure using Encryption?",
"answer": "Communication",
"hint": "Read the above paragraph for answer"
}
]
},
{
"content": [
{
"type": "text",
"text": "Now, let's take a real life example to understand where Encryption can be used."
},
{
"type": "text",
"text": "Suppose Alice and Bob share a secret key k, and Alice wants to transmit a message m to Bob over a network while maintaining the secrecy of m in the presence of an eavesdropping adversary. This tutorial begins the development of basic techniques to solve this problem. Besides transmitting a message over a network, these same techniques allow Alice to store a file on a disk so that no one else with access to the disk can read the file, but Alice herself can read the file at a later time."
},
{
"type": "question",
"question": "What Alice and Bob can use to secure message while transmission?",
"answer": "A secret key",
"hint": "Read the above paragraph for answer"
}
]
}
]
'''
Modules containing Tutorials classes for Encryption
'''
import os
import json
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from modules.parser import tutorial_parser
Builder.load_file('./ui/encryption/tutorials.kv')
class TutorialBox(BoxLayout):
'''
TutorialBox class to present available Tutorials
'''
class BackToTutorialsMenu(BoxLayout):
'''
BackToTutorialsMenu class presents back button and Tutorial title
'''
class Tutorials(BoxLayout):
'''
Tutorials class for Encryption
'''
pass
def __init__(self, **kwargs):
super(Tutorials, self).__init__(**kwargs)
self.all_tutorials = {}
self.removed_tutorials_menu = None
with open('data/root.json') as data:
json_data = json.loads(data.read())
self.encryption_data = json_data[4]["encryption"]
for key, value in self.encryption_data[0]["tutorials"][0].items():
value['title'] = key
tutorial_key = '_'.join(key.lower().split())
self.all_tutorials[tutorial_key] = value
self.populate_tutorials_menu()
def populate_tutorials_menu(self):
'''
populate_tutorials_menu gathers the information about the tutorials and
populates it on the tutorials menu in GUI
'''
difficulty_palette = {
'Beginner': (0.015, 0.588, 1, 1),
'Intermediate': (0.2, 0.792, 0.498, 1),
'Advance': (0.890, 0.090, 0.039, 1),
}
for key, value in self.all_tutorials.items():
tutorial_title = value['title']
tutorial_difficulty = value["difficulty"]
tutorial_color = difficulty_palette[tutorial_difficulty]
tutorial_box_widget = TutorialBox()
tutorial_box_widget.ids['tutorial_button'].bind(on_press=self.open_tutorial)
tutorial_box_widget.id = key # pylint: disable=invalid-name
tutorial_box_widget.canvas.before.children[0].rgba = tutorial_color
tutorial_box_widget.ids['tutorial_box_title'].text = tutorial_title
tutorial_box_widget.ids['tutorial_box_difficulty'].text = tutorial_difficulty
self.ids['tutorials_menu'].add_widget(tutorial_box_widget)
@staticmethod
def get_tutorial_modules(tutorial_to_import):
'''
return requested tutorial by calling get_tutorial_widget of tutorial_parser
'''
dir_name = os.path.dirname(__file__).split('modules')[1]
tutorial_to_import_path = 'modules' + dir_name + '/' + 'all_tutorials/' + tutorial_to_import
return tutorial_parser.get_tutorial_widget(tutorial_to_import_path)
def open_tutorial(self, button_object):
'''
Opens selected tutorial from the Menu
'''
tutorial_id = button_object.parent.parent.id
self.removed_tutorials_menu = self.children[0]
self.remove_widget(self.children[0])
box_layout = BoxLayout()
box_layout.id = 'tutorials_menu' # pylint: disable=invalid-name
box_layout.orientation = 'vertical'
back_to_tutorial_menu = BackToTutorialsMenu()
back_to_tutorial_menu.ids['tutorial_title'].text = self.all_tutorials[tutorial_id]['title']
back_to_tutorial_menu.ids['tutorials_menu_button'].bind(
on_press=self.back_to_tutorials_menu
)
box_layout.add_widget(back_to_tutorial_menu)
box_layout.add_widget(self.get_tutorial_modules(tutorial_id))
self.add_widget(box_layout)
def back_to_tutorials_menu(self, button_object):
'''
back_to_tutorials_menu removes the tutorial widget and replaces tutorials menu
'''
self.remove_widget(button_object)
self.remove_widget(self.children[0])
self.add_widget(self.removed_tutorials_menu)
'''
Helps parse tutorials using json files and build widgets accordingly for the UI
'''
import json
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.core.window import Window
Builder.load_file('./ui/tutorial_parser.kv')
class LessonScreenManager(ScreenManager):
'''
LessonScreenManager is used to handle multiple lessons of a tutorial
'''
class LessonScreen(Screen):
'''
LessonScreen is used to define single screen for the LessonScreenManager
'''
class LessonContent(BoxLayout):
'''
LessonContent is used to hold different lesson objects
'''
class LessonNavigation(BoxLayout):
'''
LessonNavigation is used to create navigation bar for the screen in order to
switch from one lesson to another
'''
class PreviousLessonButton(Button):
'''
PreviousLessonButton is used to switch to previous lesson
'''
class NextLessonButton(Button):
'''
NextLessonButton is used to switch to next lesson
'''
class LessonHeader(BoxLayout):
'''
LessonHeader is used to show Lesson number
'''
class LessonLabelBox(BoxLayout):
'''
LessonLabelBox is used to display text type content
'''
class LessonQuestionBox(BoxLayout):
'''
LessonQuestionBox is used to display question type content
'''
class LessonImageBox(BoxLayout):
'''
LessonImageBox is used to display image type content
'''
class LessonCodeBox(BoxLayout):
'''
LessonCodeBox is used to display code type content
'''
def get_tutorial_widget(tutorial_to_import_path):
'''
get_tutorial_widget imports json tutorial and try to build widget tree for the UI
'''
lesson_screen_manager = LessonScreenManager()
with open(tutorial_to_import_path + '.json') as data:
tutorial = json.load(data)
lesson_no = 0
for lesson in tutorial:
lesson_no += 1
lesson_screen = LessonScreen(name=str(lesson_no))
lesson_content = LessonContent()
lesson_header = LessonHeader()
lesson_header.ids['lesson_header_label'].text = 'Lesson ' + str(lesson_no)
lesson_content.ids['scroll_tutorial_content_box'].add_widget(lesson_header)
for content_part in lesson['content']:
lesson_content_widget = get_tutorial_content_widget(content_part)
lesson_content.ids['scroll_tutorial_content_box'].add_widget(lesson_content_widget)
lesson_navigation = get_lesson_navigation(lesson_screen_manager, tutorial, lesson_no)
lesson_content.ids['scroll_tutorial_content_box'].add_widget(lesson_navigation)
lesson_screen.add_widget(lesson_content)
lesson_screen_manager.add_widget(lesson_screen)
return lesson_screen_manager
def get_lesson_navigation(lesson_screen_manager, tutorial, lesson_no):
'''
get_lesson_navigation builds and return navigation buttons for a lesson
'''
lesson_navigation = LessonNavigation()
if lesson_no > 1:
previous_lesson_button = PreviousLessonButton()
def navigate_backward(button_object):
'''
navigate_backward navigates screen to previous lesson of the tutorial
'''
lesson_screen_manager.transition.direction = 'right'
lesson_screen_manager.current = button_object.id
previous_lesson_button.id = str(lesson_no - 1) # pylint: disable=invalid-name
previous_lesson_button.bind(on_press=navigate_backward)
lesson_navigation.add_widget(previous_lesson_button)
else:
lesson_navigation.add_widget(FloatLayout())
if not lesson_no < len(tutorial):
lesson_navigation.add_widget(FloatLayout())
else:
next_lesson_button = NextLessonButton()
def navigate_forward(button_object):
'''
navigate_forward navigates screen to next lesson of the tutorial
'''
lesson_screen_manager.transition.direction = 'left'
lesson_screen_manager.current = button_object.id
next_lesson_button.id = str(lesson_no + 1) # pylint: disable=invalid-name
next_lesson_button.bind(on_press=navigate_forward)
lesson_navigation.add_widget(next_lesson_button)
return lesson_navigation
def get_tutorial_content_widget(content_part): # pylint: disable=inconsistent-return-statements
'''
get_tutorial_content_widget
'''
if content_part['type'] == 'text':
text = content_part['text']
lesson_box = LessonLabelBox()
lesson_box.ids['lesson_label'].text = text
def change_lesson_label(*args):
'''
change_lesson_label changes dimensions of label and
it's parent with every change of width of Window
'''
window_width = args[1]
lesson_box.ids['lesson_label'].width = window_width
lesson_box.ids['lesson_label'].texture_update()
lesson_box.ids['lesson_label'].padding = [20, 0]
lesson_box.height = lesson_box.ids['lesson_label'].texture_size[1]
change_lesson_label(Window, Window.width)
Window.bind(width=change_lesson_label)
return lesson_box
if content_part['type'] == 'question':
question_box = LessonQuestionBox()
question_box.ids['lesson_question_label'].text = content_part['question']
if content_part['hint']:
question_box.ids['lesson_question_input'].hint_text = content_part['hint']
def on_answer_change(*_):
'''
on_answer_change resets validation messages when user changes answer
'''
question_box.ids['lesson_answer_validation'].text = ''
question_box.ids['lesson_question_input'].bind(text=on_answer_change)
def on_submit_answer(*_):
'''
on_submit_answer is triggered when answer is submitted with and validated
accordingly
'''
if question_box.ids['lesson_question_input'].text == content_part['answer']:
question_box.ids['lesson_answer_validation'].color = [0, 1, 0, 1]
question_box.ids['lesson_answer_validation'].text = 'Your answer is correct!'
else:
question_box.ids['lesson_answer_validation'].color = [1, 0, 0, 1]
question_box.ids['lesson_answer_validation'].text = 'Your answer is incorrect!'
question_box.ids['lesson_submit_answer'].bind(on_press=on_submit_answer)
return question_box
if content_part['type'] == 'image':
if content_part['url']:
lesson_image_box = LessonImageBox()
lesson_image_box.ids['lesson_image_src'].source = content_part['url']
def change_lesson_image_box(*args):
'''
change_lesson_image_box changes dimensions of image box
with every change of width of Window
'''
window_width = args[1]
if window_width / 2 < 350:
lesson_image_box.height = 350
elif window_width / 2 > 500:
lesson_image_box.height = 500
else:
lesson_image_box.height = window_width / 2
change_lesson_image_box(Window, Window.width)
Window.bind(width=change_lesson_image_box)
return lesson_image_box
if content_part['type'] == 'code':
lesson_code_box = LessonCodeBox()
lesson_code_box.ids['lesson_code_block'].text = content_part['code']
return lesson_code_box
......@@ -105,7 +105,6 @@ class SignUp(BoxLayout, Screen):
Prompting error message to the user otherwise
'''
app_object = args[0]
app_object.switch_screen_to_dashboard()
if self.validate():
email = self.ids['user_email'].text
password = self.ids['first_pass'].text
......
......@@ -4,9 +4,9 @@
size_hint: 1, 0.9
id: encryption_content_box
canvas.before:
Color:
Color
rgba: 1, 1, 1, 1
Rectangle:
Rectangle
pos: self.pos
size: self.size
BoxLayout
......@@ -26,9 +26,9 @@
<RadioNavButton@ButtonBehavior+BoxLayout>
canvas.before:
Color:
Color
rgba: 0, 0, 0, 1
Rectangle:
Rectangle
pos: self.pos
size: self.size
......
<Tutorials>:
Label:
text: 'Encryption Tutorials'
\ No newline at end of file
<Tutorials>
ScrollView
size_hint: None, None
size: root.size
GridLayout
id: tutorials_menu
padding: dp(9)
spacing: dp(9)
cols: 2
size_hint: 1, None
height: self.minimum_height
orientation: 'vertical'
<TutorialBox>
orientation: 'vertical'
padding: (10, 25, 10, 25)
size_hint_y: None
height: 150
canvas.before:
Color
rgba: 0.5, 1, 0.5, 1
RoundedRectangle
pos: self.pos
size: self.size
Label
id: tutorial_box_title
text_size: self.width, None
size: self.texture_size
text: 'Tutorial Title'
font_name: 'ui/assets/fonts/VarelaRound-Regular.ttf'
font_size: 20
line_height: 1
color: 0, 0, 0, 1
halign: 'left'
valign: 'top'
BoxLayout
Button
text: 'Open'
id: tutorial_button
size_hint: 0.4, 0.8
font_name: 'ui/assets/fonts/VarelaRound-Regular.ttf'
background_color: 0, 0, 0, 1
Label
id: tutorial_box_difficulty
text_size: self.width, None
size: self.texture_size
text: 'Tutorial Difficulty'
font_name: 'ui/assets/fonts/VarelaRound-Regular.ttf'
font_size: 20
halign: 'right'
valign: 'bottom'
<BackToTutorialsMenu>
size_hint: 1, 0.1
padding: (0, 10, 0, 0)
BoxLayout
size_hint: 0.2, 1
padding: (10, 0, 0, 0)
Button
text: 'Back'
id: tutorials_menu_button
font_name: 'ui/assets/fonts/VarelaRound-Regular.ttf'
background_color: 0, 0, 0, 1
BoxLayout
size_hint: 0.8, 1
padding: (0, 0, 70, 0)
Label
text: 'Tutorial Title'
id: tutorial_title
font_name: 'ui/assets/fonts/VarelaRound-Regular.ttf'
<LessonContent>
ScrollView
size_hint: None, None
size: root.size
GridLayout
id: scroll_tutorial_content_box
padding: dp(0)
spacing: dp(0)
cols: 1
spacing: 20
size_hint: 1, None
height: self.minimum_height
orientation: 'vertical'
<LessonNavigation>
size_hint_y: None
height: 70
padding: 0, 20, 0, 0
<PreviousLessonButton>
text: 'Previous Lesson'
font_name: 'ui/assets/fonts/VarelaRound-Regular.ttf'
<NextLessonButton>
text: 'Next Lesson'
font_name: 'ui/assets/fonts/VarelaRound-Regular.ttf'
<LessonHeader>
orientation: 'vertical'
size_hint_y: None
height: 50
Label
id: lesson_header_label
color: 0, 0, 0, 1
text_size: self.width, None
size: self.texture_size
font_name: 'ui/assets/fonts/VarelaRound-Regular.ttf'
font_size: 30
halign: 'center'
<LessonLabelBox>
orientation: 'vertical'
size_hint_y: None
Label
id: lesson_label
color: 0, 0, 0, 1
text_size: self.width, None
size: self.texture_size
font_name: 'ui/assets/fonts/VarelaRound-Regular.ttf'
font_size: 20
halign: 'justify'
markup: True
on_ref_press:
import webbrowser
webbrowser.open(args[1])
<LessonQuestionBox>
orientation: 'vertical'
size_hint_y: None
height: 150
padding: 20, 0, 20, 0
BoxLayout
size_hint: 1, 0.5
Label
id: lesson_question_label
color: 0, 0, 0, 1
text_size: self.width, None
size: self.texture_size
font_name: 'ui/assets/fonts/VarelaRound-Regular.ttf'
font_size: 20
halign: 'center'
BoxLayout
halign: 'center'
size_hint: 1, 0.3
BoxLayout
size_hint: 0.6, 1
TextInput
id: lesson_question_input
font_name: 'ui/assets/fonts/VarelaRound-Regular.ttf'
font_size: 20
multiline: False
write_tab: False
BoxLayout
size_hint: 0.4, 1
Button
id: lesson_submit_answer
background_color: 0, 0, 0, 1