Skip to content

Commit

Permalink
Merge pull request #1 from ab-smith/swagger
Browse files Browse the repository at this point in the history
Swagger
  • Loading branch information
ab-smith authored Jul 2, 2019
2 parents 87d86fe + f126e42 commit a990f31
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 52 deletions.
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()

0 comments on commit a990f31

Please sign in to comment.