Commit bbcb9797 authored by Sanyam Khurana's avatar Sanyam Khurana

feat(encryption_tools): Add encryption tools

Adding encryption tools

See merge request new-contributor-wizard-team/new-contributor-wizard!7
parents 05b5d18a aea2bcb2
# Project Tools
modules/encryption/tools/all_tools/gnupg_home
# Project directories
gnupg_home
# Python
*.pyc
......
......@@ -8,7 +8,6 @@ before_script:
- apt-get install -y ffmpeg git
- pip3 install pipenv
- pipenv install --skip-lock
- pipenv install --skip-lock git+http://github.com/kivy/kivy.git#egg=kivy-1.10.1
pylint:
type: test
......@@ -21,5 +20,6 @@ pylint:
pytest:
type: test
script:
- apt-get install -y gnupg2
- pipenv install --skip-lock pytest pytest-cov
- pipenv run pytest tests --cov=modules
......@@ -7,9 +7,12 @@ name = "pypi"
pylint = "==1.9.1"
pytest = "==3.6.0"
pytest-cov = "==2.5.1"
ipdb = "==0.11"
[packages]
cython = "==0.28"
kivy = "==1.10.1"
python-gnupg = "==0.4.3"
requests = "==2.19.1"
[requires]
......
This diff is collapsed.
v0.0.1
## June 19 2018
- Adding Encryption module skeleton (Shashank Kumar)
- Adding Encryption tools (create key pair, display and manage key pair, encrypt message and decrypt message) (Shashank Kumar)
## June 11 2018
- Adding Dashboard feature (Shashank Kumar)
......
[
{"application_settings": []},
{"blog": []},
{"cli": []},
{"communication": []},
{"encryption":[
{
"tutorials": []
},
{
"tools": [
{
"Display and manage key pair": {
"difficulty": "Beginner"
},
"Create key pair": {
"difficulty": "Beginner"
},
"Encrypt a message": {
"difficulty": "Intermediate"
},
"Decrypt a message": {
"difficulty": "Intermediate"
}
}
]
}
]
},
{"how_to_use": []},
{"profile_settings": []},
{"theme_settings": []},
{"vcs": []},
{"way_ahead": []}
]
......@@ -35,7 +35,8 @@ sudo apt-get install -y \
libswscale-dev \
libavformat-dev \
libavcodec-dev \
zlib1g-dev
zlib1g-dev \
gnupg2
# Install gstreamer for audio, video (optional)
sudo apt-get install -y \
......@@ -52,11 +53,7 @@ Step 4: Install application dependencies (this might take a while, grab a cup of
`$ pipenv install`
Step 5: Install Kivy
`$ pipenv install --skip-lock git+http://github.com/kivy/kivy.git#egg=kivy-1.10.1`
Step 6: Run New Contributor Wizard
Step 5: Run New Contributor Wizard
`$ pipenv run python main.py`
......
......@@ -4,12 +4,44 @@ Modules containing Encryption classes
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from modules.encryption.tutorials import tutorials
from modules.encryption.tools import tools
Builder.load_file('./ui/encryption.kv')
Builder.load_file('./ui/encryption/encryption.kv')
class Encryption(BoxLayout):
'''
Encryption class for tutorials and tools
'''
pass
def __init__(self, **kwargs):
super(Encryption, self).__init__(**kwargs)
self.all_options = {
'tutorials': tutorials.Tutorials(),
'tools': tools.Tools(),
}
self.all_options_items = list(self.all_options.keys())
def enable_option(self, option_to_enable):
'''
enable_menu function focuses on concerned menu items or settings which is clicked and
removes focus from all other menu items and settings
'''
option_to_enable_widget = self.ids[option_to_enable + '_box']
option_to_enable_color = option_to_enable_widget.canvas.before.children[0].rgba
if option_to_enable_color != [1, 1, 1, 1]:
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)
# removing enabled option from the list in order to disable all other options
options_to_disable = self.all_options_items[:]
options_to_disable.remove(option_to_enable)
for option in options_to_disable:
self.ids[option + '_box'].canvas.before.children[0].rgba = [0, 0, 0, 1]
self.ids[option].color = (1, 1, 1, 1)
self.ids['encryption_content_box'].remove_widget(self.all_options[option])
self.ids['encryption_content_box'].add_widget(self.all_options[option_to_enable])
'''
This modules helps display and manage key pairs
'''
import logging
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.popup import Popup
from kivy.lang import Builder
from kivy.clock import Clock
from modules.encryption.tools.all_tools.exceptions import GPGError
from modules.encryption.tools.all_tools.services import create_gpg_key_pair
from modules.encryption.tools.all_tools.validations import (
validate_email, validate_name, validate_comment, validate_expire_date
)
Builder.load_file('./ui/encryption/all_tools/create_key_pair.kv')
class CreateKeyPairPopup(Popup):
'''
CreateKeyPairPopup displays popup to inform about key creation progress
'''
pass
class CreateKeyPair(BoxLayout):
'''
CreateKeyPair helps integrate UI with helper functions
'''
def prompt_error_message(self, label, error_text):
'''
Displays error message on the UI on the respective label widget
'''
original_text = self.ids[label].text
self.ids[label].text = error_text
self.ids[label].color = [1, 0, 0, 1]
def replace_label(*args):
'''
Replacing original text in label
delay time is defined by args[0]
'''
logging.info(
'\'%s\' changed to \'%s\' after %s seconds',
error_text,
original_text,
args[0]
)
self.ids[label].text = original_text
self.ids[label].color = [0, 0, 0, 1]
Clock.schedule_once(replace_label, 2)
def validate(self):
'''
Validating user input
'''
name = self.ids['input_name'].text
email = self.ids['input_email'].text
comment = self.ids['input_comment'].text
expire_date = self.ids['input_expire_date'].text
validation_successful = True
try:
validate_name(name)
except GPGError as error:
validation_successful = False
self.prompt_error_message(
'label_name',
error.message
)
try:
validate_email(email)
except GPGError as error:
validation_successful = False
self.prompt_error_message(
'label_email',
error.message
)
try:
validate_comment(comment)
except GPGError as error:
validation_successful = False
self.prompt_error_message(
'label_comment',
error.message
)
try:
validate_expire_date(expire_date)
except GPGError as error:
validation_successful = False
self.prompt_error_message(
'label_expire_date',
error.message
)
return validation_successful
def creating_key_pair(self):
'''
Processing user input to create key pair
'''
creating_key_pair_popup = CreateKeyPairPopup()
def add_button(*args):
'''
Add Key fingerprint to label and button
'''
creating_key_pair_popup.ids['create_gpg_key_pair_popup_label'].text = args[0]
if self.validate():
name = self.ids['input_name'].text
email = self.ids['input_email'].text
comment = self.ids['input_comment'].text
expire_date = self.ids['input_expire_date'].text
try:
creating_key_pair_popup.open()
key_fingerprint = create_gpg_key_pair(
name=name,
email=email,
comment=comment,
expire_date=expire_date
)
message = 'Key has been created with\n{}\nfingerprint'.format(
key_fingerprint)
add_button(message)
except GPGError as error:
add_button(error.message)
'''
This modules helps decrypt a message using private key
'''
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.lang import Builder
from modules.encryption.tools.all_tools.exceptions import GPGError
from modules.encryption.tools.all_tools.services import (
list_gpg_all_keys, decrypt_message, create_key_listing_widget
)
Builder.load_file('./ui/encryption/all_tools/decrypt_a_message.kv')
class KeyColumnBox(GridLayout):
'''
KeyColumnBox helps contain widgets and display them at the center of the box
'''
class DecryptKeyBox(BoxLayout):
'''
DecryptKeyBox helps contain widgets and display them at the center of the box
'''
class KeyInfoLabel(Label):
'''
KeyInfoLabel helps display key information
'''
class DisplayAndManageKeyPair(BoxLayout):
'''
DisplayAndManageKeyPair helps integrate UI with helper functions
'''
class DecryptMessagePopup(Popup):
'''
DecryptMessagePopup helps take encrypted message and passphrase and display
decrypted message on a popup
'''
class NoKeyPresentDecrypt(BoxLayout):
'''
NoKeyPresentDecrypt will be displayed in case if no key is present
'''
class DecryptAMessage(BoxLayout):
'''
DecryptAMessage integrated UI with helper functions
'''
def __init__(self, **kwargs):
super(DecryptAMessage, self).__init__(**kwargs)
all_keys = list_gpg_all_keys()
self.populate_with_keys(all_keys['all_private_keys'])
def populate_with_keys(self, all_private_keys):
'''
populate_with_keys displays all the available private keys that can be
used to decrypt message
'''
if all_private_keys.items():
for key_column_box in create_key_listing_widget(
self.decrypt_message_popup, all_private_keys, DecryptKeyBox,
KeyColumnBox, KeyInfoLabel
):
self.ids['scroll_view_box'].add_widget(key_column_box)
else:
self.ids['scroll_view_box'].clear_widgets()
self.ids['scroll_view_box'].add_widget(NoKeyPresentDecrypt())
@staticmethod
def decrypt_message_popup(*args):
'''
decrypt_message_popup allows user to decrypt a message using passphrase
and encrypted message
'''
decrypt_message_popup_object = DecryptMessagePopup()
def get_decrypted_message(*args):
'''
get_decrypted_message receives all the data from input box in order
to fetch decrypted message
'''
if args:
encrypted_message = decrypt_message_popup_object.ids['encrypted_message'].text
passphrase = decrypt_message_popup_object.ids['passphrase_input'].text
decrypt_message_object = decrypt_message_popup_object.ids['decrypted_message']
if not passphrase:
decrypt_message_object.text = 'Enter Passphrase'
elif encrypted_message:
try:
decrypted_message = decrypt_message(encrypted_message, passphrase)
if decrypted_message:
decrypt_message_object.text = decrypted_message
else:
decrypt_message_object.text = 'Incorrect Passphrase'
except GPGError as error:
decrypt_message_object.text = error.message
else:
decrypt_message_object.text = ''
decrypt_message_popup_object.ids['encrypted_message'].bind(
text=get_decrypted_message
)
decrypt_message_popup_object.ids['passphrase_input'].bind(
text=get_decrypted_message
)
if args:
decrypt_message_popup_object.open()
'''
This modules helps display and manage key pairs
'''
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.lang import Builder
from modules.encryption.tools.all_tools.utils import extract_key_uid_info
from modules.encryption.tools.all_tools.services import (
list_gpg_all_keys, export_single_key
)
Builder.load_file('./ui/encryption/all_tools/display_and_manage_key_pair.kv')
class KeyColumnBox(GridLayout):
'''
KeyColumnBox helps contain widgets and display them at the center of the box
'''
class KeyBox(BoxLayout):
'''
KeyBox helps contain widgets and display them at the center of the box
'''
class KeyInfoLabel(Label):
'''
KeyInfoLabel helps display key information
'''
class PublicKeyPopup(Popup):
'''
PublicKeyPopup helps display Public Key in UTF-8 inside a popup
'''
class PrivateKeyPopup(Popup):
'''
PrivateKeyPopup helps display Private Key in UTF-8 inside a popup
'''
class NoKeyPresent(BoxLayout):
'''
NoKeyPresent will be displayed in case if no key is present
'''
class DisplayAndManageKeyPair(BoxLayout):
'''
DisplayAndManageKeyPair helps integrate UI with helper functions
'''
def __init__(self, **kwargs):
super(DisplayAndManageKeyPair, self).__init__(**kwargs)
all_keys = list_gpg_all_keys()
self.populate_with_keys(
all_keys['all_public_keys'],
all_keys['all_private_keys']
)
def populate_with_keys(self, all_public_keys, all_private_keys):
'''
populate_with_keys displays all the available public and private keys
'''
if all_public_keys.items():
for fingerprint, key_info in all_public_keys.items():
user_info = extract_key_uid_info(key_info['uids'][0])
key_column_box = KeyColumnBox()
key_info_label = KeyInfoLabel(
text='\n'.join(user_info.values())
)
key_column_box.add_widget(key_info_label)
# Spliting fingerprint to multiple lines to make it better on the UI
# pylint: disable=invalid-name
FINGERPRINT_LENGTH_BY_HALF = len(fingerprint) // 2
fingerprint_text = fingerprint[:FINGERPRINT_LENGTH_BY_HALF] + '\n' +\
fingerprint[FINGERPRINT_LENGTH_BY_HALF:]
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'].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'].bind(
on_press=self.display_private_key
)
key_column_box.add_widget(key_box)
self.ids['scroll_view_box'].add_widget(key_column_box)
else:
self.ids['scroll_view_box'].clear_widgets()
self.ids['scroll_view_box'].add_widget(NoKeyPresent())
@staticmethod
def display_public_key(*args):
'''
display_public_key helps display public key in plain text to the correspoding
key fingerprint
'''
fingerprint = args[0].id
public_key_popup = PublicKeyPopup()
public_key = export_single_key(fingerprint)
public_key_popup.ids['public_key_text_display'].text = public_key
public_key_popup.open()
@staticmethod
def display_private_key(*args):
'''
display_private_key helps display private key in plain text to the correspoding
key fingerprint and passphrase
'''
fingerprint = args[0].id
def get_private_key(*args):
'''
get_private_key calls helper function to get private key in plain text
'''
passphrase = args[1]
if passphrase:
private_key = export_single_key(fingerprint, passphrase)
if private_key:
private_key_popup.ids['private_key_text_display'].text = private_key
else:
private_key_popup.ids['private_key_text_display'].text = 'Incorrect Passphrase'
private_key_popup = PrivateKeyPopup()
private_key_popup.ids['private_key_passphrase_input'].bind(
text=get_private_key
)
private_key_popup.open()
'''
This module helps encrypt a message using public key
'''
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.lang import Builder
from modules.encryption.tools.all_tools.services import (
list_gpg_all_keys, encrypt_message, create_key_listing_widget
)
Builder.load_file('./ui/encryption/all_tools/encrypt_a_message.kv')
class KeyColumnBox(GridLayout):
'''
KeyColumnBox helps contain widgets and display them at the center of the box
'''
class EncryptKeyBox(BoxLayout):
'''
EncryptKeyBox helps contain widgets and display them at the center of the
box
'''
class KeyInfoLabel(Label):
'''
KeyInfoLabel helps display key information
'''
class DisplayAndManageKeyPair(BoxLayout):
'''
DisplayAndManageKeyPair helps integrate UI with helper functions
'''
class EncryptMessagePopup(Popup):
'''
EncryptMessagePopup helps encrypt plain text into encrypted message
'''
class NoKeyPresentEncrypt(BoxLayout):
'''
NoKeyPresentEncrypt will be displayed in case if no key is present
'''
class EncryptAMessage(BoxLayout):
'''
EncryptAMessage integrated UI with helper functions
'''
def __init__(self, **kwargs):
super(EncryptAMessage, self).__init__(**kwargs)
all_keys = list_gpg_all_keys()
self.populate_with_keys(all_keys['all_public_keys'])
def populate_with_keys(self, all_public_keys):
'''
populate_with_keys displays all available public keys
'''
if all_public_keys.items():
for key_column_box in create_key_listing_widget(
self.encrypt_message_popup, all_public_keys, EncryptKeyBox,
KeyColumnBox, KeyInfoLabel
):
self.ids['scroll_view_box'].add_widget(key_column_box)
else:
self.ids['scroll_view_box'].clear_widgets()
self.ids['scroll_view_box'].add_widget(NoKeyPresentEncrypt())
@staticmethod
def encrypt_message_popup(*args):
'''
encrypt_message_popup allows user to encrypt a message from plain text
'''
fingerprint = args[0].id
encrypt_message_popup_object = EncryptMessagePopup()
def get_encrypted_message(*args):
'''
get_encrypted_message receives all the data from input box in order
to fetch encrypted message
'''
plain_message = args[1]
if plain_message:
encrypted_message = encrypt_message(fingerprint, plain_message)
encrypt_message_popup_object.ids['encrypted_message'].text = encrypted_message
else:
encrypt_message_popup_object.ids['encrypted_message'].text = ''
encrypt_message_popup_object.ids['plain_message'].bind(
text=get_encrypted_message
)
encrypt_message_popup_object.open()
'''
Exceptions module contains exception classes specific to encryption.tools module
'''
class GPGError(Exception):
'''
GPGError class can be used to raise exception related to
User's imput
'''
def __init__(self, message):
self.message = message
super().__init__(message)
'''
Service functions for encryption.tools module
'''
from subprocess import check_output
import gnupg
from modules.encryption.tools.all_tools.exceptions import GPGError
from modules.encryption.tools.all_tools.utils import extract_key_uid_info
GNUPG_HOME = 'gnupg_home'
IS_KEY_PRIVATE = True
def create_gnupg_object():
'''
Creating and returning GnuPG object
'''
gpg_binary_path = check_output(
'which gpg2', shell=True).decode().strip('\n')
if gpg_binary_path:
gpg = gnupg.GPG(gnupghome=GNUPG_HOME, gpgbinary=gpg_binary_path)
gpg.encoding = 'utf-8'
return gpg
raise GPGError('''Please install gpg2 using your Operating System\'s
package manager''')