Ruby TOTP
Ruby TOTP
• Ruby
• IIJ SmartKey *1 iOS
*1 "IIJ SmartKey ". h1p://
www.iij.ad.jp/smartkey/
iOS D !
• D
• h$p://hioki-daichi.jp/passwordd.html
•
• h$ps://github.com/hioki-daichi/passwordd
otpauth://totp/github.com/hioki-daichi
?issuer=GitHub&secret=njjlrjgljcebmj6l
otpauth://totp/github.com/hioki-daichi
?issuer=GitHub&secret=njjlrjgljcebmj6l
njjlrjgljcebmj6l
! 165853" 372144# 770782
...
Ruby ✨
hmac = OpenSSL::HMAC.digest( OpenSSL::Digest.new('sha1'), Base32.decode('NJJLRJGLJCEBMJ6L'), [Time.now.to_i / 30].pack('N*').rjust(8, 0.chr))#=> "n\xEA\xD6\xBF\xFB\xA1\xA6\xB2\x128# \x1A\xB0\x8D\x1DR\xD4\x8F\xE6\xD5\xAE"
hmac.unpack('[H*]').pop#=> "6eead6bffba1a6b212381ab08d1d52d48fe6d5ae"
-------------------------------------------------------------|6e|ea|d6|bf|fb|a1|a6|b2|12|38|1a|b0|8d|1d|52|d4|8f|e6|d5|ae|------------------------------------------------------------|
offset = hmac[-1].ord & 0xfcode = (hmac[offset ].ord & 0x7f) << 24 | (hmac[offset + 1].ord & 0xff) << 16 | (hmac[offset + 2].ord & 0xff) << 8 | (hmac[offset + 3].ord & 0xff)(code % 10 ** 6).to_s.rjust(6, '0')#=> "662182"
-------------------------------------------------------------|6e|ea|d6|bf|fb|a1|a6|b2|12|38|1a|b0|8d|1d|52|d4|8f|e6|d5|ae|-------------------------------------------***********----++| 0xae & 0xf #=> 14 0x52d48fe6 #=> 1389662182 ~~~~~~
otpauth://totp/github.com/hioki-daichi
?issuer=GitHub&secret=njjlrjgljcebmj6l
otpauth://totp/github.com/hioki-daichi
?issuer=GitHub&secret=njjlrjgljcebmj6l&algorithm=SHA256
&digits=8&period=10
Key Uri Format*2
*2 "Key Uri Format · google/google-authen8cator Wiki". GitHub. h@ps://github.com/google/google-authen8cator/wiki/Key-Uri-Format
TypeREQUIRED
otpauth://totp/ACME%20Co:[email protected]?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=AC
ME%20Co&algorithm=SHA1&digits=6&period=30
• totp / hotp
LabelREQUIRED
otpauth://totp/ACME%20Co:[email protected]?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=AC
ME%20Co&algorithm=SHA1&digits=6&period=30
• secret
• "#{issuer}:#{accountname}" !
SecretREQUIRED
otpauth://totp/ACME%20Co:[email protected]?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=A
CME%20Co&algorithm=SHA1&digits=6&period=30
• 128 160
• Base32 stesla/base32*3
*3 "stesla/base32: A library which provides base32 decoding and encoding.".GitHub. h?ps://github.com/stesla/base32
IssuerSTRONGLY RECOMMENDED
otpauth://totp/ACME%20Co:[email protected]?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=AC
ME%20Co&algorithm=SHA1&digits=6&period=30
• Label
• Label Parameters !
AlgorithmOPTIONAL
otpauth://totp/ACME%20Co:[email protected]?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=AC
ME%20Co&algorithm=SHA1&digits=6&period=30
• SHA1 (Default) / SHA256 / SHA512
DigitsOPTIONAL
otpauth://totp/ACME%20Co:[email protected]?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=AC
ME%20Co&algorithm=SHA1&digits=6&period=30
• 6 (Default) / 8
• 6 10 ** 6
PeriodOPTIONAL
otpauth://totp/ACME%20Co:[email protected]?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=AC
ME%20Co&algorithm=SHA1&digits=6&period=30
• 30
HOTP OTP
!
Gem !
mdp/rotp*4
totp = ROTP::TOTP.new( "BASE32SECRET3232", interval: 60, issuer: "ACME Co", digits: 8, digest: "sha256")#=> #<ROTP::TOTP:0x007fde9244c028# @interval=60, @issuer="ACME Co",# @digits=8, @digest="sha256",# @secret="BASE32SECRET3232">
*4 "mdp/rotp: Ruby One Time Password library".GitHub h?ps://github.com/mdp/rotp
mdp/rotp*4
totp.now#=> "24430035"
totp.provisioning_uri("[email protected]")#=> "otpauth://totp/# ACME%20Co:[email protected]# ?secret=BASE32SECRET3232# &period=60# &issuer=ACME+Co&digits=8"
*4 "mdp/rotp: Ruby One Time Password library".GitHub h?ps://github.com/mdp/rotp
mdp/rotp*4
totp.verify("24430035")#=> false
totp.verify_with_drift("24430035", 10)#=> true
*4 "mdp/rotp: Ruby One Time Password library".GitHub h?ps://github.com/mdp/rotp
TOTP
!
•
• e.g. SMS
SMS
QR !
QR
• UI
!
( )
• ( )
!
secret
• SecureRandom
IIJ SmartKey *5
*5 "IIJ SmartKey ". h1p://www.iij.ad.jp/biz/smartkey-m/
②
$ curl $API_ENDPOINT/apps/$APP_ID/accounts/$ACCOUNT_ID/notifications-X POST-H 'Content-Type: application/json'-H 'X-Iij-Smart-Key-Api-Key: $API_KEY'-d '{ "title":"GitHub ",
"message":"GitHub ",
"push_notification_title":" ",
"push_notification_message":" "
}'
⑥
$ curl $API_ENDPOINT/apps/$APP_ID/accounts/$ACCOUNT_ID/notifications...
{ "key":"b89609af119c3a94fb05b60c15bb8807", "account_code":"728f190fa43069c449411ecef22b550cd0a1edbf", "title":"GitHub ",
"message":"GitHub ",
"status":"verified", "notified_at":"2016-06-16T00:00:00.000+09:00"}
• RFC6238
• TOTP: Time-Based One-Time Password Algorithm
• h?ps://tools.ieC.org/html/rfc6238
• RFC4226
• HOTP: An HMAC-Based One-Time Password Algorithm
• h?ps://tools.ieC.org/html/rfc4226
• RFC2104
• HMAC: Keyed-Hashing for Message AuthenNcaNon
• h?ps://tools.ieC.org/html/rfc2104
• RFC4648
• The Base16, Base32, and Base64 Data Encodings
• h?ps://tools.ieC.org/html/rfc4648