Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swagger #1

Merged
merged 4 commits into from
Jul 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
FROM python:alpine3.10
MAINTAINER Abderrahmane SMIMITE

RUN apk add build-base openssl-dev libffi-dev vim
RUN pip install cffi cryptography flask
RUN apk add build-base openssl-dev libffi-dev vim py-gunicorn

RUN mkdir /app
COPY requirements.txt /app
COPY app.py /app
COPY wsgi.py /app
COPY start.sh /app
WORKDIR /app

RUN pip install -r requirements.txt

EXPOSE 5000

CMD ["python3", "app.py"]
CMD ["/app/start.sh"]
118 changes: 71 additions & 47 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from flask import Flask,jsonify,request,abort
from flask_restplus import Resource, Api, fields, reqparse
import json

import base64
Expand All @@ -9,6 +10,16 @@

from cryptography.fernet import Fernet


flask_app = Flask(__name__)
app = Api(app = flask_app,
version = "1.0",
title = "EOF (Encryption On the Fly)",
description = "Manage real-time encryption for your app with a simple API. Based on Fernet implementation which uses 128-bit AES in CBC mode and PKCS7 padding, with HMAC using SHA256. Proof Of Concept API with NO INFORMATION STORED.")

name_space = app.namespace('v1', description='Encryption on the fly API')


def genKey(password_provided):
password = password_provided.encode()
salt = b'rrdX9A66qXtQZwzf' # You NEED TO CHANGE THIS (eg. os.urandom(16)) must be of type bytes
Expand All @@ -22,68 +33,81 @@ def genKey(password_provided):
key = base64.urlsafe_b64encode(kdf.derive(password)) # Can only use kdf once
return key

app = Flask(__name__)

'''
Secure Transport (TLS) is mandatory.
This snippet is minimalist on purpose so to keep processing on the memory
'''
@app.route("/", methods=('GET',))
def hello():
return "App is Up!"
EncryptThis = app.model('Encrypt This', {
'key': fields.String(required=True, description='Your encryption password that will be used to derivate the key'),
'plaintext': fields.String(required=True, description='Data to encrypt')
})

DecryptThis = app.model('Decrypt This', {
'key': fields.String(required=True, description='Your encryption password used to derivate the key'),
'ciphertext': fields.String(required=True, description='Data to decrypt')
})

@name_space.route('/health')
class Health(Resource):
def get(self):
'''Return system health status'''
return {'status': 'Everything looks fine'}

@app.route("/encrypt", methods=['POST'])
def encrypt():

@name_space.route('/encrypt')
class Encryption(Resource):
'''
{
"key":"secretKey",
"plaintext":"Text containing sensitive data to be encrypted"
}
'''
req_data = request.get_json()

try:
key = req_data['key']
plaintext = req_data['plaintext']
except:
abort(400)

message = plaintext.encode()

try:
f = Fernet(genKey(key))
encrypted = f.encrypt(message)
except:
abort(403)

return json.dumps({'ciphertext':encrypted.decode()})


@app.route("/decrypt", methods=['POST'])
def decrypt():
@name_space.expect(EncryptThis)
def post(self):
'''Get a plaintext and the associated key and return ciphertext'''
try:
key = name_space.payload['key']
plaintext = name_space.payload['plaintext']
except:
abort(400)

message = plaintext.encode()

try:
f = Fernet(genKey(key))
encrypted = f.encrypt(message)
except:
abort(403)

return {'ciphertext':encrypted.decode()}


@name_space.route('/decrypt')
class Decryption(Resource):
'''
{
"key":"secretKey",
"ciphertext":"gAAAAABdGQQgxejDKPqkR9tMGdHsL0ewJr3z3TOZeNC7-0AxBIxCv3gjAmng4ZrIY668ovifRMl1_F_5O64Wjbhn0qsm2Vn7UjbEhOEvXFlFIaK1ichVONWHr0sMGD5s30TNf7_9LEKN"
}
'''
req_data = request.get_json()
try:
key = req_data['key']
ciphertext = req_data['ciphertext']
except:
abort(400)

encrypted = ciphertext.encode()

try:
f = Fernet(genKey(key))
decrypted = f.decrypt(encrypted)
except:
abort(403)

return json.dumps({'plaintext':decrypted.decode()})

if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000)
@name_space.expect(DecryptThis)
def post(self):
'''Get a ciphertext and the associated key and return plaintext'''
try:
key = name_space.payload['key']
ciphertext = name_space.payload['ciphertext']
except:
abort(400)

encrypted = ciphertext.encode()

try:
f = Fernet(genKey(key))
decrypted = f.decrypt(encrypted)
except:
abort(403)

return {'plaintext':decrypted.decode()}

if __name__ == '__main__':
flask_app.run(debug=False)
6 changes: 4 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
cffi==1.12.3
cryptography==2.6.1
Flask==1.0.2
flask_restplus==0.12.1
cryptography==2.6.1
cffi==1.12.3
gunicorn==19.9.0
3 changes: 3 additions & 0 deletions start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env ash
cd /app
gunicorn --bind 0.0.0.0:5000 wsgi:flask_app
4 changes: 4 additions & 0 deletions wsgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from app import flask_app

if __name__ == "__main__":
flask_app.run()