following these steps below:
- install package
racket-base32
:
raco pkg install https://github.com/sackpost/racket-base32.git
- test it:
raco test google-auth.rkt
#lang racket/base | |
(require base32 | |
file/sha1 | |
web-server/stuffers/hmac-sha1 | |
racket/contract) | |
(define/contract (get-code key) | |
(-> bytes? integer?) | |
(let* ([key (base32-decode key)] | |
[code (hex-string->bytes | |
(string-append "0" | |
(number->string (round (/ (current-seconds) 30)) 16)))] | |
[fdb (bytes-append | |
(apply bytes-append | |
(for/list ([_ (- 8 (bytes-length code))]) | |
(bytes 0))) | |
code)] | |
[hmac (HMAC-SHA1 key fdb)] | |
[o (bitwise-and (bytes-ref hmac 19) 15)] | |
[h (subbytes hmac o (+ o 4))] | |
[q1 (arithmetic-shift | |
(+ (arithmetic-shift (bytes-ref h 0) 8) | |
(bytes-ref h 1)) | |
16)] | |
[q2 (+ (arithmetic-shift (bytes-ref h 2) 8) | |
(bytes-ref h 3))] | |
[qq (+ q1 q2)] | |
[mid (bitwise-and qq #x7fffffff)]) | |
(remainder mid 1000000))) | |
(module+ test | |
(displayln (get-code #"VBKVUBKHV4EB2IEB"))) |