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
80,000 Plaintext Passwords: An Open Source Love...
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
T.J. Schuck
June 26, 2014
Programming
1.2k
5
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
80,000 Plaintext Passwords: An Open Source Love Story in Three Acts
T.J. Schuck
June 26, 2014
Other Decks in Programming
See All in Programming
Snowflake Openflow Connector利用の勘所 / 20261024developersio2026tokyo-snowflake-openflow
kasacchiful
PRO
0
260
LLM 101
dalinaum
0
420
Modernizing iOS Apps
seyfoyun
0
140
[2026-10-14](C)Re:ゼロから始める異世界生活〜始まりの終わりと終わりの始まり〜
tosite
0
180
クラウドエージェントは、 何がそんなに便利なのか / what makes cloud agents so useful
rkaga
4
660
Kotlinize Is Not Just Converting to Kotlin
chigichan24
1
210
3回つくってわかった、 定期実行ジョブ基盤の本質情報
takai
4
3.5k
dotNET_vulnclicker_intro.pdf
deka_morita
0
160
AI駆動開発4年目の現在地(『あなたはFDEになるべきか?』イベント資料)
kumaiu
0
110
Railsのためのパスキー実践入門 〜マルチテナントSaaSでの意思決定〜
utakaha
3
2.1k
コーディング自動化の次へ。人の介入をゼロにするファクトリーとサポートAIによる実践
timakin
5
4.9k
No More NoSuchMethodError
exoego
1
120
Featured
See All Featured
Embracing the Ebb and Flow
colly
88
5.2k
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.4k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
510
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
20k
Accessibility Awareness
sabderemane
1
280
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
1
650
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.7k
Design in an AI World
tapps
1
380
Heart Work Chapter 1 - Part 1
lfama
PRO
10
37k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
310
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
18k
GitHub's CSS Performance
jonrohan
1033
470k
Transcript
80,000 Plaintext Passwords @tjschuck
Act I
mallory@local$ ′
None
T.J. Schuck @tjschuck
HARVEST getHarvest.com
I am not a Security Expert™
mallory@local$ ′
Layers Layers Layers Layers
mallory@local$ perl haxor.pl ′
mallory@local$ perl haxor.pl ! +------+-----------------------+------------+ | id | email |
password | +------+-----------------------+------------+ | 6125 |
[email protected]
| honeyd | | 6126 |
[email protected]
| blowfish | | 6127 |
[email protected]
| peppercorn | | 6128 |
[email protected]
| md1947 | +------+-----------------------+------------+
“But…”
mallory@local$ perl haxor.pl ! +------+-----------------------+------------+ | id | email |
password | +------+-----------------------+------------+ | 6125 |
[email protected]
| honeyd | | 6126 |
[email protected]
| blowfish | | 6127 |
[email protected]
| peppercorn | | 6128 |
[email protected]
| md1947 | +------+-----------------------+------------+
mallory@local$ perl haxor.pl ! +------+-----------------------+------------+ | id | email |
password | +------+-----------------------+------------+ | 6125 |
[email protected]
| ubarlq | | 6126 |
[email protected]
| oybjsvfu | | 6127 |
[email protected]
| crccrepbea | | 6128 |
[email protected]
| zq1947 | +------+-----------------------+------------+
Encryption is reversible
Hashing is irreversible
None
hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f
hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f hash(‘secret1234’) => bdfc2db0aa599f5919e565c328216a51
hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f hash(‘secret1234’) => bdfc2db0aa599f5919e565c328216a51 => 18ad6448e70b7b0254cad4d77653f2d7
hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f hash(‘secret1234’) => bdfc2db0aa599f5919e565c328216a51 => 18ad6448e70b7b0254cad4d77653f2d7 ?
Hashing is deterministic
None
hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f
hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f
hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f
Hashing is deterministic (but not obvious)
hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f !
hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f ! hash(‘Peppercorn’) => b8bfa4f1b72ee60755a71dbdf0700fe9
hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f ! hash(‘Peppercorn’) => b8bfa4f1b72ee60755a71dbdf0700fe9
=> b8bfa4f1b72ee60755a71dbdf0700fe8
hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f ! hash(‘Peppercorn’) => b8bfa4f1b72ee60755a71dbdf0700fe9
=> b8bfa4f1b72ee60755a71dbdf0700fe8 ?
mallory@local$ perl haxor.pl ! +------+-----------------------+----------------------------------+ | id | email |
password | +------+-----------------------+----------------------------------+ | 6125 |
[email protected]
| 6ee717a4bc91d99170ce0d0922ab6c43 | | 6126 |
[email protected]
| b258a419ddbc13d92b8e7fc25c2b9d6c | | 6127 |
[email protected]
| 6a58d0ad2619df7d7fabc2603b79063f | | 6128 |
[email protected]
| 0304432f4c8080781f1b210c6b92b12f | +------+-----------------------+----------------------------------+
Hashing is deterministic
hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f
None
Rainbow Tables
mallory@local$ perl haxor.pl ! +------+-----------------------+----------------------------------+ | id | email |
password | +------+-----------------------+----------------------------------+ | 6125 |
[email protected]
| 6ee717a4bc91d99170ce0d0922ab6c43 | | 6126 |
[email protected]
| b258a419ddbc13d92b8e7fc25c2b9d6c | | 6127 |
[email protected]
| 6a58d0ad2619df7d7fabc2603b79063f | | 6128 |
[email protected]
| 0304432f4c8080781f1b210c6b92b12f | +------+-----------------------+----------------------------------+
None
6a58d0ad2619df7d7fabc2603b79063f
None
None
Defeating the Rainbow
hash(‘peppercorn’) => 6a58d0ad2619df7d7fabc2603b79063f
hash(‘peppercorn-tc5gplQopZ617zRQ8h9pAg’) => c5dde1b5cc0e6d89bda0f5e350bda319
None
WE DID IT!
(no we didn’t)
Proof of Concept
peppercorn
pepper8 pepper83 pepper88 pepper99 ! pepperdog pepperi1 peppermint peppermint1 pepperoni
pepperpepper peppers peppers4 peppi123 peppone pepsi pepsi1 pepsi123 pepsi2006 pepsi5 pepsi78bottle pepsicat pepsico pepsii pepsimax pepsione pepsis12 pequot per12fect peralta1 peppercorn
un1v3r53 1q2w#E$R fkg7h4f3v6
SALTING
SALTING
hash(‘peppercorn-tc5gplQopZ617zRQ8h9pAg’) => c5dde1b5cc0e6d89bda0f5e350bda319 hash(‘peppercorn-R1XrmmZVRedKMTE9nlIy9Q’) => fc5ad4a64796506086424af78f57df9d
mallory@local$ perl haxor.pl ! +------+----------------------------------+------------------------+ | id | password |
salt | +------+----------------------------------+------------------------+ | 6125 | 5b5f47a49cdd4386611ee0a63577eccd | CeVDwwrT7saa_cY2rV_qng | | 6126 | a50f4854739e10773c99d5576dbb2f73 | rRWjkN4ioELXIPpQ6aDY4w | | 6127 | 94c91484c8bb05113b28f9da2b7ea624 | XvALmgae9uUGmpikd8sohg | | 6128 | 5d2ee837249e9340624b12e653c5e4a3 | D-ZUYoaSadkCze1fPibbgg | +------+----------------------------------+------------------------+
This is pretty good…
This is pretty good… for 1976.
None
None
None
None
bcrypt ✓ One-way hash ✓ Pre-image resistant ✓ Deterministic ✓
Built-in per-password salts
Eksblowfish
Adaptive Cost
mallory@local$ perl haxor.pl ! +-----------------------+--------------------------------------------------------------+ | email | password |
+-----------------------+--------------------------------------------------------------+ |
[email protected]
| $2a$10$1ObnU/cPb3AjVU5iu8ntfe77xO83roRhoJMyBqYhlq5ZMMbHCcELK | |
[email protected]
| $2a$10$CelbCnmBjJez5ego4w.mbusfnZGOn/lRhLjrr37R0iUCr1UIC6ZyC | |
[email protected]
| | |
[email protected]
| $2a$10$9WLufYmucbh.yaTHKKUuUeihbcA3hBUiI.XiW7ygmaYcYXtl4MBKy | +-----------------------+--------------------------------------------------------------+ $ 2a 10 LrfFlMh6Yc7JWKlpRwVjUuPCOPU5574fXAVrvLZRFT87cT55oLBEe $ $
$ 2a 10 LrfFlMh6Yc7JWKlpRwVjUuPCOPU5574fXAVrvLZRFT87cT55oLBEe $ $
$ 2a 10 LrfFlMh6Yc7JWKlpRwVjUu PCOPU5574fXAVrvLZRFT87cT55oLBEe $ $
$ 2a 10 LrfFlMh6Yc7JWKlpRwVjUu PCOPU5574fXAVrvLZRFT87cT55oLBEe $ $
$ 2a 10 LrfFlMh6Yc7JWKlpRwVjUu PCOPU5574fXAVrvLZRFT87cT55oLBEe $ $
$ 2a 10 LrfFlMh6Yc7JWKlpRwVjUu PCOPU5574fXAVrvLZRFT87cT55oLBEe $ $
$ 2a 10 LrfFlMh6Yc7JWKlpRwVjUu PCOPU5574fXAVrvLZRFT87cT55oLBEe $ $
$ 2a 10 LrfFlMh6Yc7JWKlpRwVjUu PCOPU5574fXAVrvLZRFT87cT55oLBEe $ $ “Cost”
None
bcrypt(‘peppercorn’, 10) =>
bcrypt(‘peppercorn’, 10) => $2a$10$41JmpddjOSEGWU099uQx7O7Y1EiQMTRQFZCcFqFMlYWekR5pj9xFi
bcrypt(‘peppercorn’, 10) => $2a$10$41JmpddjOSEGWU099uQx7O7Y1EiQMTRQFZCcFqFMlYWekR5pj9xFi bcrypt(‘peppercorn’, 10) =>
bcrypt(‘peppercorn’, 10) => $2a$10$41JmpddjOSEGWU099uQx7O7Y1EiQMTRQFZCcFqFMlYWekR5pj9xFi bcrypt(‘peppercorn’, 10) => $2a$10$8ONmT2oiKPoPn/KQTrvHq.gWTnqQ5p.T13lw.lCm9d.QoqIZzbHPS
bcrypt(‘peppercorn’, 10) => $2a$10$41JmpddjOSEGWU099uQx7O7Y1EiQMTRQFZCcFqFMlYWekR5pj9xFi bcrypt(‘peppercorn’, 10) => $2a$10$8ONmT2oiKPoPn/KQTrvHq.gWTnqQ5p.T13lw.lCm9d.QoqIZzbHPS bcrypt(‘peppercorn’, 14)
=>
bcrypt(‘peppercorn’, 10) => $2a$10$41JmpddjOSEGWU099uQx7O7Y1EiQMTRQFZCcFqFMlYWekR5pj9xFi bcrypt(‘peppercorn’, 10) => $2a$10$8ONmT2oiKPoPn/KQTrvHq.gWTnqQ5p.T13lw.lCm9d.QoqIZzbHPS bcrypt(‘peppercorn’, 14)
=> $2a$14$4US.NV/qyRkctl.LaYvNzOln70yIaqGfJeMq1deb/bPJMMmtcxOU.
bcrypt(‘peppercorn’, 10) => $2a$10$41JmpddjOSEGWU099uQx7O7Y1EiQMTRQFZCcFqFMlYWekR5pj9xFi bcrypt(‘peppercorn’, 10) => $2a$10$8ONmT2oiKPoPn/KQTrvHq.gWTnqQ5p.T13lw.lCm9d.QoqIZzbHPS bcrypt(‘peppercorn’, 14)
=> $2a$14$4US.NV/qyRkctl.LaYvNzOln70yIaqGfJeMq1deb/bPJMMmtcxOU.
bcrypt(‘peppercorn’, 10) => $2a$10$41JmpddjOSEGWU099uQx7O7Y1EiQMTRQFZCcFqFMlYWekR5pj9xFi bcrypt(‘peppercorn’, 10) => $2a$10$8ONmT2oiKPoPn/KQTrvHq.gWTnqQ5p.T13lw.lCm9d.QoqIZzbHPS bcrypt(‘peppercorn’, 14)
=> $2a$14$4US.NV/qyRkctl.LaYvNzOln70yIaqGfJeMq1deb/bPJMMmtcxOU. 0.0656 seconds
bcrypt(‘peppercorn’, 10) => $2a$10$41JmpddjOSEGWU099uQx7O7Y1EiQMTRQFZCcFqFMlYWekR5pj9xFi bcrypt(‘peppercorn’, 10) => $2a$10$8ONmT2oiKPoPn/KQTrvHq.gWTnqQ5p.T13lw.lCm9d.QoqIZzbHPS bcrypt(‘peppercorn’, 14)
=> $2a$14$4US.NV/qyRkctl.LaYvNzOln70yIaqGfJeMq1deb/bPJMMmtcxOU. 0.0656 seconds 0.0657 seconds
bcrypt(‘peppercorn’, 10) => $2a$10$41JmpddjOSEGWU099uQx7O7Y1EiQMTRQFZCcFqFMlYWekR5pj9xFi bcrypt(‘peppercorn’, 10) => $2a$10$8ONmT2oiKPoPn/KQTrvHq.gWTnqQ5p.T13lw.lCm9d.QoqIZzbHPS bcrypt(‘peppercorn’, 14)
=> $2a$14$4US.NV/qyRkctl.LaYvNzOln70yIaqGfJeMq1deb/bPJMMmtcxOU. 0.0656 seconds 0.0657 seconds 1.0481 seconds
Cost Seconds 9 0.0344 10 0.0656 11 0.1333 12 0.2646
13 0.5236 14 1.0481 15 2.1645 16 4.2801
“Well, actually…”
The Fix
def authenticate(plaintext_password)! if old_hashing_method(plaintext_password) == password_digest! self! end! end
def authenticate(plaintext_password)! if BCrypt::Password.new(password_digest) == plaintext_password! self! end! end
def authenticate(plaintext_password)! return unless convert_old_hash_to_bcrypt(plaintext_password)! ! if BCrypt::Password.new(password_digest) == plaintext_password!
self! end! end
def convert_old_hash_to_bcrypt(plaintext_password)! return true if BCrypt::Password.valid_hash?(password_digest)! ! if old_hashing_method(plaintext_password) ==
password_digest! update_column :password_digest,! BCrypt::Password.create(plaintext_password)! end! end
None
None
None
—Act II—
Fat Binary Gems —Act II— You make the rockin’ world
go ’round
bcrypt-ruby github.com/codahale/bcrypt-ruby
None
None
None
None
None
None
None
None
None
None
None
None
None
None
Well shit.
None
None
rake-compiler-dev-box with Rubies, GCC, JDK, MinGW…
None
LOLOLOLOL NO.
None
rake-compiler#79
Act III
Act III Luis Lavena
None
• One-Click Ruby Installer for Windows
• One-Click Ruby Installer for Windows • Ruby core
• One-Click Ruby Installer for Windows • Ruby core •
Ruby Hero (2010)
• One-Click Ruby Installer for Windows • Ruby core •
Ruby Hero (2010) • rake-compiler
rake-compiler-dev-box#2
None
None
None
None
None
@luislavena <3 <3 <3
Find your Luis
“Be the Luis you wish to see in the world”
What have we learned?
1. Just use bcrypt
2. Distribute a dev box
3. Release, collaborate, iterate
Thank You @tjschuck getHarvest.com