Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
you know nothing server
Search
Jameson
August 16, 2014
Technology
78
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
you know nothing server
http://pygotham.org/talks/67
I know nothing :(
Jameson
August 16, 2014
Other Decks in Technology
See All in Technology
AIにシークレットを見せない、WSL2で安全な開発環境
yazm
0
300
Kiro Crewをはじめよう
kizawa2020
1
160
Getting Started with Google Antigravity
glaforge
0
310
分析AIエージェントを育てる、動く環境を育てる
codatum
1
1.1k
JAWSUG TOHOKU 青森支部 「LoGoチャット」のAWS移行で 乗り越えたこと
taketakekaho
0
340
スプシの手作業からの解脱 ~更新はClaude Codeに、見せ方と使い方はGASアプリに任せる~
kentarofujii
0
150
Persisting Massive Data with Rails ~Designing for 60 billion rows, and fighting the bottlenecks~ Railsで挑む大量データ永続化 〜600億件を永続化するための設計とボトルネックとの戦い〜
occhi
0
730
OptunaHub: ブラックボックス最適化のためのプラットフォーム
pfn
PRO
0
140
ソフトウェア ファクトリー - 再現性のあるソフトウェアの工場づくり / Software factory
iktakahiro
6
5k
パスキーの自動テストはどこまでいけるのか
teamlab
PRO
0
260
Running Kotlin + Quarkus with Lambda
nealle
1
3.8k
DGX Spark でどこまでハッキングができるのか?
kash1064
3
1.3k
Featured
See All Featured
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.2k
Test your architecture with Archunit
thirion
2
2.4k
Navigating Weather and Climate Data
rabernat
0
560
The Mindset for Success: Future Career Progression
greggifford
PRO
0
540
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Become a Pro
speakerdeck
PRO
31
6.3k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
The browser strikes back
jonoalderson
0
1.8k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.6k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.7k
Context Engineering - Making Every Token Count
addyosmani
9
1.2k
Transcript
you know nothing server (encrypted messaging) A32A8211
Hi, I’m @jamesonjlee
(secure data storage api)
So
Encrypted Messaging
Why?
It’s a hard problem.
Yes? $36.3M Munies $60M Munies
No?
¯\_(ツ)_/¯
Disclaimer
I don’t actually “know” crypto
Don’t believe in what I am saying blindly
End Disclaimer
So
Let’s say you have a (super) secret (business) plan
None
A Classic (cryptographic) Story !
!
None
None
!
!
None
“Crypto” • HMAC (SHA) • Symmetric (AES) • Asymmetric (RSA)
• Hybrid (mix-and-match)
Asymmetric Private Key <-> Public Key Public Key (Encrypt) Private
Key (Decrypt, Sign, Auth)
None
Choose Wisely RSA DSA …?
GPG • Gnu Privacy Guard implements OpenPGP • https://www.gnupg.org/gph/en/manual.html •
(openpgp is a hybrid cipher)
! encrypts a message for using ’s Pub-Key
! store the encrypted message on ’s server
retrieves the message from ’s server
decrypt’s using ’s Private Key
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
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
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()
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
There are some holes..
Who is you?
You is who?
Verify?
Verify!
Client? <——> Server?
Client? <— NSA —> Server?
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
SSL/TLS Handshake! http://www-01.ibm.com/support/knowledgecenter/SSFKSJ_7.1.0/com.ibm.mq.doc/sy10660_.htm?lang=en
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()
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
None
Nope
:(
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()
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
You is who?
Identity Distribution
Public Key Infrastructure
None
Web of Trust
None
WoT vs PKI
wot wot, wot, wot • http://pgp.mit.edu • http://keyserver.pgp.com
wot wot, wot, wot • http://pgp.mit.edu • http://keyserver.pgp.com • …
wot wot, wot, wot • http://pgp.mit.edu • http://keyserver.pgp.com • …
• … • … • … • …
wot wot, wot, wot • http://pgp.mit.edu • http://keyserver.pgp.com • …
• … • … • … • … • … • … • … • … • … • …
None
! http://sks-keyservers.net/
None
¯\_(ツ)_/¯
(new!) https://keybase.io
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
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
None
¯\_(ツ)_/¯
What done? Swimming Pool Cloud
None
Anonymous!
demo-ish
final thoughts
Forward Secrecy
Plausible Deniability
Cool Stuffs • DNSSEC • Off-The-Record • Perfect Forward Secrecy
• GPG Internals • MFA Possession Factors (http://pyvideo.org/ video/2699/multi-factor-authentication- possession-factors)
just sign mine Don’t just sign random keys
Don’t just sign random keys
Tanks! source on github: jamesonjlee/simple-secret-app