# CryptoWallet to Encrypt Files
###### tags: `Bloom Week1`
## :scroll: GitHub Repo for the Project ➜ [PyCryption](https://github.com/ShivaShanmuganathan/PyCryption)
## :mag: How does it work?
## :camera: UML diagrams
### Shan wants to send a `message` to Shiva
```sequence
Shan->Shiva: Request for Shiva's Public Key
Shiva-->Shan: Sends Public Key
Note left of Shan: Encrypts message
Note left of Shan: Sign encrypted message
Shan->Shiva: Sends Encrypted Message
Shan->Shiva: Sends Signature
Shan->Shiva: Sends Public Key
Note right of Shiva: Verify Sign using Public Key
Note right of Shiva: Decrypt message
```
## :book: Detailed Explaination
1. Alice requests for Bob's `public_key`
2. Alice performs `symmetric encryption` on the `message`
3. Alice encrypts the `symmetric_key` using Bob's public key
4. Alice signs the `encrypted_message` using Alice's `private_key`
5. Alice sends the `public_key` of Alice, `encrypted_message`, and `signature` to Bob
6. Bob verifies the `encrypted_message` using the signature and Alice's `public_key`.
7. Bob decryptes the `encrypted_message` using Bob's `private_key`
## :rocket: Features
- [x] Perform both Symmetric & Asymmetric Encryption
- [x] Signing messages
- [x] Verifying signature
- [x] Encrypting messages
- [x] Decrypting messages
- [x] Dockerized the application
## 🖭 How does each file work?
### :rocket: [create_keys.py](https://github.com/ShivaShanmuganathan/PyCryption/blob/master/create_keys.py)
- Using RSA to generate Public and Private key of Receiver
```
import rsa
#----------CREATING RECEIVER'S PUBLIC & PRIVATE KEYS------------#
# CREATE THE PUB & PRIVATE KEYS
(pubkey,privkey)=rsa.newkeys(2048)
# WRITE THE PUBLIC KEY TO A FILE
pukey = open('publickey.key','wb')
pukey.write(pubkey.save_pkcs1('PEM'))
pukey.close()
# WRITE THE PRIVATE KEY TO A FILE
prkey = open('privkey.key','wb')
prkey.write(privkey.save_pkcs1('PEM'))
prkey.close()
print('PUBLIC & PRIVATE KEY OF RECEIVER HAS BEEN GENERATED')
```
---
### :rocket: [encrypt.py](https://github.com/ShivaShanmuganathan/PyCryption/blob/master/encrypt.py)
### Alice performs encryption and signs the message
- Perform `Symmetric Encryption` on the `Message`
- Encrypt `Symmetric_Key` using Bob's `Public_Key`
- Generate `public_key` and `private_key` for Alice
- Sign the `encrypted_message` using Alice's `private_key`
### These 4 Files need to be sent to Bob
##### 1. `encrypted_symmetric_key`
##### 2. Alice's `public_key`
##### 3. `signature`
##### 4. `encrypted_message`
```
from cryptography.fernet import Fernet
import rsa
#----------FILE ENCRYPTION USING SYMMETRIC KEY---------------#
# CREATE THE SYMMETRIC KEY AND CIPHER
symKey = Fernet.generate_key()
cipher = Fernet(symKey)
# GET FILENAME TO ENCRYPT
filename = input("Enter filename to encrypt [with extension]:\n")
myfile = open(filename,'rb')
myfiledata = myfile.read()
# ENCRYPT THE DATA AND CREATE ENCRYTPED FILE
encrypted_data = cipher.encrypt(myfiledata)
edata = open('enc_' + filename ,'wb')
edata.write(encrypted_data)
#----------USING RECEIVER'S PUBLIC KEY TO ENCRYPT SYMMETRIC KEY------------#
# OPEN AND LOAD THE PUBLIC KEY FILE OF RECEIVER
pkey = open('publickey.key','rb')
pkdata = pkey.read()
pubkey = rsa.PublicKey.load_pkcs1(pkdata)
# ENCRYPT THE SYMMETRIC KEY WITH THE PUBLIC KEY
encrypted_key = rsa.encrypt(symKey,pubkey)
ekey = open('encrypted_key','wb')
ekey.write(encrypted_key)
#----------USING SENDER'S PRIVATE KEY TO SIGN MESSAGE------------#
# GENERATE ASYMMETRIC KEY PAIR [to use for signature]
(public_key, private_key) = rsa.newkeys(512)
vkey = open('public_verify.key','wb')
vkey.write(public_key.save_pkcs1('PEM'))
vkey.close()
# GENERATE SIGNATURE FILE
signature = rsa.sign(encrypted_data, private_key, 'SHA-1')
sign = open('sign.txt','wb')
sign.write(signature)
sign.close()
print('------- ENCRYPTION COMPLETE ---------')
print('\n')
print(' YOU CAN NOW SHARE THE ENCRYPTED FILE: _enc' +filename+ '\n' );
print(' YOU CAN NOW SHARE THE ENCRYPTED SYMMETRIC KEY: encrypted_key \n' );
print(' YOU CAN NOW SHARE THE PUBLIC KEY OF SENDER: public_verify.key \n' );
print(' YOU CAN NOW SHARE THE SIGNATURE: sign.txt \n' );
```
---
### :rocket: [decrypt.py](https://github.com/ShivaShanmuganathan/PyCryption/blob/master/decrypt.py)
### Bob performs decryption and verifies the message
- Bob's `private_key` is used to decrypt the `encrypted_symmetric_key`
- `symmetric_key` is used to decrypt the `Message`
- `signature` is verified using Alice's `public_key`
### Bob can now access the decrypted message.
```
import rsa
from cryptography.fernet import Fernet
# OEPN RECEIVER'S PRIVATE KEY [to decrypt the symmetric key]
prkey = open('privkey.key','rb')
pkey = prkey.read()
private_key = rsa.PrivateKey.load_pkcs1(pkey)
# DECRYPT SYMMETRIC KEY USING RECEIVER'S PRIVATE KEY
s = open('encrypted_key','rb')
sym = s.read()
symKey = rsa.decrypt(sym,private_key)
cipher = Fernet(symKey)
# DECRYPTION USING CIPHER OF SYMMETRIC KEY
filename = input("Enter filename to decrypt [with extension]:\n")
encrypted_data = open(filename,'rb')
edata = encrypted_data.read()
decrypted_data = cipher.decrypt(edata)
message = decrypted_data
# OPENING THE PUBLIC KEY OF SENDER AND SIGNATURE
vkey = open('public_verify.key','rb')
vdata = vkey.read()
public_verify = rsa.PublicKey.load_pkcs1(vdata)
sign = open('sign.txt','rb')
signature = sign.read()
# VERIFYING SIGNATURE
try:
rsa.verify(edata, signature, public_verify)
print('signature verified')
# load the file
with open('decrypted_' + filename,'wb') as df:
df.write(decrypted_data)
print('Check----->'+ 'decrypted_'+filename+ '<------to get the decrypted file')
except:
print('message is tampered')
```