ã¯ããã«
Railsã§èªèšŒæ©èœãå®è£ ããŠãããšãããã¹ã¯ãŒãã®ããã·ã¥ã«ã€ããŠèª¿ã¹ãŠããŸããã
Railsã®ææã ãšããã°ã€ã³æ©èœã®å®è£
ã«ã¯äººæ°ã®èªèšŒã©ã€ãã©ãªdevise
ã䜿ããªãå Žåã« bcrypt
ã©ã€ãã©ãªã䜿ã£ãŠããããšãå€ãã§ãããäžæ¹ã§ OpenSSL::Digest::SHA256
ã䜿ã£ãŠèªåã§ããã·ã¥åããæ¹æ³ãååšããŸãã
SHA256 ãš bcryptããåã âããã·ã¥åâ ãªã®ã«ãäœãéãã®ïŒã ãšæããã®èšäºãæžãããšã«ããŸããã
ãsha256 bcrypt éãããªã©ã®ã¯ãŒãã§Googleæ€çŽ¢ããŠã¿ãŸãããã2ã€ã®éãã«ã€ããŠã»ãã¥ãªãã£ã®èгç¹ãããã£ãã解説ãããæ¥æ¬èªã®èšäºã¯æå€ãšå°ãªãå°è±¡ã§ãã
æ¬èšäºã§ã¯ããã®éããã³ãŒããšå®äŸã§ãããããã解説ããŠãããŸãã
ç®æ¬¡
- ãããããããã·ã¥åããšã¯ïŒæå·åãšäœãéãã®ïŒ
- SHA256ãšBCryptãã©ãéãã®ïŒ
- BCryptã¯ããããšé ãã
- SHA256ã¯ãéãããããã¬ã€ã³ããŒããŒãã«æ»æãšã¯
- ãœã«ãã£ãŠäœïŒãªãå®å šãªã®ïŒ
- ãäœäžåã詊ããªãã§ãããã¯çãïŒçŸå®ã®æ»æææ³
- SHA256 vs BCrypt æ¯èŒãŸãšã
- Railsã§äœ¿ããªããããã
- çµè«:èªèšŒåŠçã§ã¯bcryptã䜿ãã
1. ãããããããã·ã¥åããšã¯ïŒæå·åãšäœãéãã®ïŒ
ããã·ã¥ãšã¯ å ¥åå€ãåºå®é·ã®å€ã«å€æããäžæ¹åæ§ã®é¢æ° ã§ããäžæ¹åæ§ãšããã®ã¯ããå ã®å€ã埩å ã§ããªãããšããæå³ã§ãã
ãã¹ã¯ãŒãã®ãããªæ©å¯æ å ±ãä¿åããéãå¹³æïŒãã®ãŸãŸã®æååïŒã§ä¿åããã®ã¯å±éºã§ããããã§ãããã·ã¥åããŠä¿åããŠãããŸãã
ããã·ã¥ â æå·å
ãããã·ã¥ããšãæå·åã㯠ãŸã£ããã®å¥ç© ã§ãã
æå·åãšã¯ãã埩å·ïŒå ã«æ»ãããšïŒããã§ããä»çµã¿ã§ããããšãã°ãå ±ééµãå ¬ééµãªã©ã䜿ã£ãŠãæå·åãããããŒã¿ãæ£èŠã®æé ã§å ã«æ»ãã ããã«ãªã£ãŠããŸãã
ãããããã·ã¥åã¯ãå ã«æ»ãããšãåæã§ã¯ãããŸãããäžæ¹åã®åŠçã§ãåãå ¥åããåžžã«åãåºåãåŸããããã®ã®ãããããå ã®å ¥åãå°ãåºãããšã¯äžå¯èœã§ãã埩å·ããã®ã§ã¯ãªãã åã颿°ã䜿ã£ãŠåèšç®ããå€ãäžèŽãããã©ããããã§ã㯠ããŸããããã«ããããã¹ã¯ãŒãã®ç §åãã§ããä»çµã¿ã«ãªã£ãŠããŸãã
2. SHA256ãšBCryptãã©ãéãã®ïŒ
ãŸãã¯ããpasswordããšããæååãããã·ã¥åããéã®æåã«ã€ããŠãRubyã®ã³ãŒãã§èŠæ¯ã¹ãŠã¿ãŸãããã
SHA256ã§ããã·ã¥å
require 'openssl'
hash = OpenSSL::Digest::SHA256.hexdigest("password")
puts hash
# => "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8"
ãpasswordããšããæååã«å¯ŸããŠãããã·ã¥å€ãäžæã«æ±ºãŸããŸãã
BCryptã§ããã·ã¥å
require 'bcrypt'
hash = BCrypt::Password.create("password")
puts hash
# => $2a$12$...ïŒæ¯åã¡ããæååãåºãïŒïŒ
ãpasswordããšããæååã«å¯ŸããŠãããã·ã¥å€ãå®è¡ãããã³ã«å€ãããŸãã
ð SHA256ã®ç¹åŸŽ
SHA256ã§ã¯ãOpenSSL::Digest::SHA256.hexdigest("password")
ã®ããã«æžããšãæ¯ååãå
¥åããåãããã·ã¥å€ãåŸãããŸããããã¯ã·ã³ãã«ã§ãããåããã¹ã¯ãŒãã¯åãããã·ã¥ã«ãªããããæ»æè
ã«ãšã£ãŠæšæž¬ãããããªããŸãã
ð BCryptã®ç¹åŸŽ
äžæ¹ãBCryptã§ã¯ BCrypt::Password.create("password")
ãšããããšã§ãæ¯åç°ãªãããã·ã¥ãçæãããŸããããã¯å
éšã§ã©ã³ãã ãªãœã«ããšããæåå(ãœã«ãã£ãŠäœïŒãªãå®å
šãªã®ïŒã§èª¬æ)ãèªåçã«å ããããŠããããã§ããåããã¹ã¯ãŒãã§ãç°ãªãããã·ã¥ã«ãªãããšã§ãæšæž¬ãæ¯èŒãå°é£ã«ãªããŸãã
3. BCryptã¯ããããšé ãã
BCryptã¯æå³çã«åŠçãé ãããŠãæ»æè ã倧éã«è©Šããªãããã«å·¥å€«ãããã¢ã«ãŽãªãºã ã§ãã
BCrypt::Password.create("password", cost: 12)
ãã® cost
ãåŠçã®éãïŒè€éãïŒã決ãããã©ã¡ãŒã¿ã§ãå€ã1å¢ãããšåŠçæéã¯ææ°é¢æ°çã«é
ããªããŸãã
cost | åŠçæéã®ç®å® |
---|---|
10 | çŽ100ms |
12 | çŽ300ms |
14 | çŽ1ç§ |
ã€ãŸããBCryptã¯ãæéããããããããšãã§å®å šæ§ãé«ããŠããã®ã§ãã
ãã ããcostãäžãããããšãŠãŒã¶ãŒäœéšã«åœ±é¿ãåºãããšã...
ã»ãã¥ãªãã£åŒ·åã®ããã« cost ãé«ãèšå®ãããããšããŠãŒã¶ãŒã«ããã¡ãªãããçããå¯èœæ§ããããŸãã
-
â ïž ãã°ã€ã³ãæ°èŠç»é²ã®åŠçãéããªã
cost=12 ã§çŽ0.3ç§ãcost=14 ã§ã¯çŽ1ç§ãcost=16 ã ãšçŽ4ç§ãããããŠãŒã¶ãŒããé ãããšæããéŸå€ã«è¿ã¥ããŠããŸãã -
â ïž å€§èŠæš¡ãµãŒãã¹ã§ã¯ãµãŒããŒè² è·ãå¢å
åæãã°ã€ã³æ°ãå€ããµãŒãã¹ã§ã¯ãç §ååŠçãããã«ããã¯ãšãªã£ãŠã¬ã¹ãã³ã¹é å»¶ãæããªã¹ã¯ããããŸãã -
â ïž UXã®æªåã«ã€ãªããæãã
å°ãã®åŸ ã¡æéã§ãããŠãŒã¶ãŒã¯ã䜿ãã¥ããããšæããŠããŸãããšããããŸãã
åèïŒdeviseã§ã¯ cost=12 ãããã©ã«ã
Railsã® devise
ã§ã¯ãBCryptã® cost
ã¯ããã©ã«ãã§ 12
ã«èšå®ãããŠããŸããããã¯ãå®å
šæ§ãšåŠçé床ã®ãã©ã³ã¹ããšããŠåºãæ¡çšãããŠããæ°å€ã§ãã
costã®èšå®ã¯ããã©ã³ã¹ããéèŠ
BCryptã®costã¯é«ããã°é«ãã»ã©å®å
šããšããããã§ã¯ãããŸããã
ã»ãã¥ãªãã£ãšããã©ãŒãã³ã¹ã®ãã©ã³ã¹ãèŠæ¥µããŠãèªåã®ãµãŒãã¹ã«åã£ãå€ãèšå®ããããšã倧åã§ãã
4. SHA256ã¯ãéãããããã¬ã€ã³ããŒããŒãã«æ»æãšã¯
SHA256ã¯éåžžã«é«éãªããã·ã¥é¢æ°ã§ãããã®æ§èœã®é«ããéã«ä»ã«ãªããŸãã
ã¬ã€ã³ããŒããŒãã«æ»æãšã¯ïŒ
ããããããã䜿ããããã¹ã¯ãŒããšãã®SHA256ããã·ã¥ãå šéšèšç®ããŠãããŠãç §åã«äœ¿ãææ³ã§ãã
OpenSSL::Digest::SHA256.hexdigest("password")
# => "5e884898da28047151d0e56f8dc62927..."
ãã®åºåã¯èª°ãã©ãã§ãã£ãŠãåãã§ããã€ãŸããæ»æè ã¯ããã®ããã·ã¥ã¯ "password" ã ããšèŠããŠããã°OKãªã®ã§ãã
ããã¯ãœã«ãããªãããèµ·ããåé¡ã§ãã
5. ãœã«ãã£ãŠäœïŒãªãå®å šãªã®ïŒ
ãœã«ããšã¯ããã¹ã¯ãŒãã«è¶³ãã©ã³ãã ãªå€ã®ããšã§ãã
BCrypt::Password.create("password")
# => "$2a$12$abc123...xxxx"ïŒæ¯åéãïŒ
ãœã«ããããããšã§ããåããã¹ã¯ãŒããã§ãæ¯åéãããã·ã¥å€ã«ãªããŸãã
æ»æè
ã¯ãæ¯åãœã«ããå«ããèšç®ãããçŽãå¿
èŠãããããã倧éã®ç
§åãéå¹çã«ãªããŸãã
# ãœã«ãããªããã°
OpenSSL::Digest::SHA256.hexdigest("password")
# => "5e884898..."ïŒèª°ã§ãåãïŒ
# ãœã«ããããã°
BCrypt::Password.create("password")
# => "$2a$12$..."ïŒæ¯åç°ãªãïŒ
ãœã«ãã¯ãã¬ãŠãOK
æ»æè
ããœã«ããç¥ã£ãŠãããã®ãœã«ãã«å¯Ÿããæ»æããŸãäžããå§ããªããã°ãããŸããã
ã€ãŸããæéãå¢ãããããšã§çŸå®çãªæ»æãé²ãã®ããœã«ãã®ç®çã§ãã
6. ãäœäžåã詊ããªãã§ãããã¯çãïŒçŸå®ã®æ»æææ³
ããã°ã€ã³ã«å€±æãããã¢ã«ãŠã³ããããã¯ããããããäœäžåã詊ããªãã§ããïŒããšããçåãåºãŠãããšæããŸãã
ã§ããæ»æè ã¯ãã°ã€ã³ç»é¢ã§è©Šãã®ã§ã¯ãããŸããã以äžã®ãããªæ¹æ³ããããŸãã
â æ¹æ³1ïŒããŒã¿ããŒã¹ãæµåºãããšãã«ãªãã©ã€ã³ã§æ»æ
äžçªå¯èœæ§ãé«ãå±éºãªã±ãŒã¹ã§ãã
æ»æè
ã users
ããŒãã«ãªã©ããããã·ã¥æžã¿ãã¹ã¯ãŒãïŒpassword_digest
ïŒãå
¥æããå Žåãèªåã®PCã§å¥œããªã ã詊ããŸãã
# æµåºããããã·ã¥å€ãããã ã£ããšãã
stored_hash = "5e884898da28047151d0e56f8dc62927..."
# æ»æè
ãèŸæžæ»æã§è©Šã
guesses = ["123456", "password", "qwerty"]
guesses.each do |guess|
if OpenSSL::Digest::SHA256.hexdigest(guess) == stored_hash
puts "ãããããŸãã! ãã¹ã¯ãŒã㯠#{guess}"
# => ãããããŸãã! ãã¹ã¯ãŒã㯠password
end
end
ãã®ããã«ããã°ã€ã³è©Šè¡åæ°ã®å¶éã¯æå³ãæã¡ãŸããã
â æ¹æ³2ïŒBotããããªã©ã䜿ã£ãåæ£æ»æ
IPã¢ãã¬ã¹å¶éããŠãŒã¶ãŒããšã®ããã¯æ©èœããã£ãŠããäžçäžã®ææPCã䜿ã£ãŠåæ£çã«æ»æããã°åé¿ã§ããŸãã
ç¹ã«SHA256ã®ããã«è»œãåŠçã ãšãããããæ»æã«èããããªãå¯èœæ§ããããŸãã
7ïŒSHA256 vs BCrypt æ¯èŒãŸãšã
é ç® | SHA256 | BCrypt |
---|---|---|
åŠçé床 | éåžžã«é«é | ãããšé ãããŠãã |
ãœã«ãå¯Ÿå¿ | ããŠããªãïŒèªåå®è£ ãå¿ èŠïŒ | èªåã§å¯Ÿå¿ |
ããã·ã¥å€ã®æ å ± | ããã·ã¥å€ã®ã¿ | costããœã«ããåã蟌ãŸãã |
ãã¹ã¯ãŒãä¿å | æšå¥šãããªã | ããã¡ã¯ãã¹ã¿ã³ããŒã |
â BCrypt㯠ãé ããŠå®å šããSHA256㯠ãéããŠå±éºã ãªã®ã§ã
8ïŒRailsã§äœ¿ããªããããã
Railsã§ã¯ãhas_secure_password
ã䜿ãããšã§BCryptã«ããã»ãã¥ã¢ãªå®è£
ããšãŠãç°¡åã«ãªããŸãã
# ãã€ã°ã¬ãŒã·ã§ã³
add_column :users, :password_digest, :string
# User model
has_secure_password
# ç»é²
User.create(name: "taro", password: "secret", password_confirmation: "secret")
# èªèšŒ
user = User.find_by(name: "taro")
user.authenticate("secret") # => userãªããžã§ã¯ããè¿ã
ãã®ä»çµã¿ã®è£ã§ã¯ãBCryptã䜿ãããŠããããœã«ããcostã®åŠçããã¹ãŠRailsããããªã«ãã£ãŠãããŸãã
9. çµè«ïŒãã°ã€ã³åŠçã§ã¯BCryptã䜿ãã
- SHA256ã¯é«éã§äŸ¿å©ã§ããããã¹ã¯ãŒãããã·ã¥ã«äœ¿ãã¹ãã§ã¯ãããŸããã
- BCryptã¯ãåŠçãé ããããœã«ãä»ãããcostã§èª¿æŽå¯èœããªã®ã§ãç·åœããæ»æã«åŒ·ãã®ã§ãã
ã»ãã¥ãªãã£ã¯ âèŠããªãéšåâ ãã倧äºã§ããBCryptã䜿ã£ãŠãå®å šãªå®è£ ãå¿ãããŸãããã
ãããã«
ãã®èšäºã§ã¯ãSHA256ãšBCryptã®éããã³ãŒããšæ»æææ³ã®èŠç¹ãã解説ããŸããã
ããã·ã¥ãšæå·åã®éãããœã«ãã®åœ¹å²ãã¬ã€ã³ããŒããŒãã«æ»æã®ãªã¹ã¯ããããŠBCryptã®åŒ·ãã
ã©ããæ®æ®µã¯æèããªããããããŸããããèªèšŒã§éåžžã«éèŠãªåºç€ç¥èã§ãã
æ¬èšäºããããªãSHA256ã§ã¯ãªãBCryptã䜿ãã®ãããšããçåã®è§£æ¶ã«åœ¹ç«ãŠã°å¹žãã§ãã