Upgrade to Pro — share decks privately, control downloads, hide ads and more …

you know nothing server

Avatar for Jameson Jameson
August 16, 2014

you know nothing server

http://pygotham.org/talks/67
I know nothing :(

Avatar for Jameson

Jameson

August 16, 2014

Other Decks in Technology

Transcript

  1. So

  2. No?

  3. So

  4. !

  5. !

  6. !

  7. code - server setup from flask import Flask, json from

    flask.ext.sqlalchemy import SQLAlchemy import config ! app = Flask(__name__) app.config.from_object(config) db = SQLAlchemy(app) ! class Message(db.Model): id = db.Column(db.Integer, primary_key=True) recipient = db.Column(db.String(128), index=True, nullable=False) message = db.Column(db.Text, nullable=False) ! def __init__(self, recipient, message): self.recipient = recipient self.message = message
  8. code - server @app.route('/message/<string:recipient_id>', methods=['GET']) def get_message_by_sig(recipient_id): messages = Message.query.filter(Message.recipient

    == recipient_id).all() return json.dumps(messages), 200 ! @app.route('/message/<string:recipient_id>', methods=['POST']) def add_message_by_sig(recipient_id): message = request.get_json() message = Message(recipient=recipient_id, message=message) db.session.add(message) db.session.commit() return 'OK', 200
  9. code - client class Client(object): def __init__(self, host, port, passphrase):

    self.host = "{host}:{port}".format(host=host, port=port) self.passphrase = passphrase self.gpg, self.fp = get_or_gen_gpg(passphrase) self.secret = ‘' ! def get_messages(self): url = self.host + "/message/{}".format(self.fp) resp = requests.get(url, auth=(self.secret, '')) decrypted = [] for message in resp.json(): decrypted.append(self._decrypt(message)) print decrypted ! def send_message(self, message): url = self.host + "/message/{}".format(self.fp) encrypted_message = self._encrypt(message) payload = json.dumps(encrypted_message) resp = requests.post(url, payload=payload, auth=(self.secret, '')) print resp.json()
  10. code - client encrypt/decrypt def _encrypt(self, message, recipient): encrypted_data =

    self.gpg.encrypt( message, recipients=[recipient], sign=self.fp, passphrase=passphrase) return encrypted_data ! def _decrypt(self, message): decrypted_data = gpg.decrypt( str(encrypted_data), passphrase=passphrase) return decrypted_data
  11. Identity Verification • I am USER, are you SERVER +

    key • I am SERVER key, are you USER key + key2 • (encrypted with key2) • I am USER, you are SERVER • Then all communication by “key2” until expiry
  12. code - reinvented client def authenticate(self): if not self.secret: self.secret

    = generate_random_string() if not self.session: self._challenge_server() return self.secret ! def _challenge_server(self): url = self.host + "/authenticate/{}".format(self.fp) message = self._encrypt(self.secret, self.server_fp) ! response = request.post(url, data=payload) if response.ok: msg = json.loads(self._decrypt(response.text)) if msg['key'] == self.secret: self.secret = msg['key2'] self.session = True else: raise Exception('Bad Server Authentication') else: self.authenticate()
  13. code - reinvented server @app.route('/authenticate/<string:recipient_id>', methods=['POST']) def authenticate_person(recipient_id): key =

    util.gpg_decrypt(app.gpg, request.data, config.SERVER_PASSPHRASE) key2 = util.generate_random_string(32) body = { 'key': str(key), 'key2': key2 } msg = json.dumps(body) server_fp = util.get_fp_from_gpg(app.gpg, config.SERVER_KEY_FP) encrypted = util.gpg_encrypt( app.gpg, server_fp, msg, recipient_id, config.SERVER_PASSPHRASE) return str(encrypted), 200
  14. :(

  15. code - reinvented client def authenticate(self): if not self.secret: self.secret

    = generate_random_string() if not self.session: self._challenge_server() return self.secret ! def _challenge_server(self): url = self.host + "/authenticate/{}".format(self.fp) message = self._encrypt(self.secret, self.server_fp) ! response = request.post(url, data=payload) if response.ok: msg = json.loads(self._decrypt(response.text)) if msg['key'] == self.secret: self.secret = msg['key2'] self.session = True else: raise Exception('Bad Server Authentication') else: self.authenticate()
  16. code - reinvented server @app.route('/authenticate/<string:recipient_id>', methods=['POST']) def authenticate_person(recipient_id): key =

    util.gpg_decrypt(app.gpg, request.data, config.SERVER_PASSPHRASE) key2 = util.generate_random_string(32) body = { 'key': str(key), 'key2': key2 } msg = json.dumps(body) server_fp = util.get_fp_from_gpg(app.gpg, config.SERVER_KEY_FP) encrypted = util.gpg_encrypt( app.gpg, server_fp, msg, recipient_id, config.SERVER_PASSPHRASE) return str(encrypted), 200
  17. wot wot, wot, wot • http://pgp.mit.edu • http://keyserver.pgp.com • …

    • … • … • … • … • … • … • … • … • … • …
  18. code - keyserver class PubKey(db.Model): id = db.Column(db.Integer, primary_key=True) fingerprint

    = db.Column(db.String(128), index=True, nullable=False) pub_key = db.Column(db.Text, nullable=False) ! def __init__(self, fingerprint, pub_key): self.fingerprint = fingerprint self.pub_key = pub_key
  19. code - keyserver @app.route('/identify/<string:fingerprint>', methods=['GET']) def get_fingerprint_pub_key(fingerprint): pub_key = PubKey.query.filter(PubKey.fingerprint==fingerprint).first()

    if pub_key: return pub_key.pub_key, '200' else: return 'Unknown Fingerprint', 404 ! @app.route('/identify/<string:fingerprint>', methods=['POST']) def add_fingerprint_pub_key(fingerprint): pub_key = PubKey(fingerprint, request.form.get('keyfile')) db.session.add(pub_key) db.session.commit() return 'OK', 200
  20. Cool Stuffs • DNSSEC • Off-The-Record • Perfect Forward Secrecy

    • GPG Internals • MFA Possession Factors (http://pyvideo.org/ video/2699/multi-factor-authentication- possession-factors)