diff options
Diffstat (limited to 'kasi-totp.el')
| -rw-r--r-- | kasi-totp.el | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/kasi-totp.el b/kasi-totp.el index 5a54397..7d97646 100644 --- a/kasi-totp.el +++ b/kasi-totp.el | |||
| @@ -55,10 +55,18 @@ string." | |||
| 55 | (when (> (length key) blocksize) | 55 | (when (> (length key) blocksize) |
| 56 | (setq key (secure-hash algorithm key))) | 56 | (setq key (secure-hash algorithm key))) |
| 57 | (when (< (length key) blocksize) | 57 | (when (< (length key) blocksize) |
| 58 | (setq key (concat key (make-string (- blocksize (length key)) 0)))) | 58 | (setq key (string-as-unibyte (concat key (make-string (- blocksize (length key)) 0))))) |
| 59 | (let ((o-key-pad (cl-map 'string #'logxor key (make-string blocksize #x5c))) | 59 | (let* ((key-list (string-to-list key)) |
| 60 | (i-key-pad (cl-map 'string #'logxor key (make-string blocksize #x36)))) | 60 | (o-key-pad (apply #'unibyte-string |
| 61 | (secure-hash algorithm (concat o-key-pad (secure-hash algorithm (concat i-key-pad message) nil nil t)) nil nil binary))) | 61 | (cl-map 'list #'logxor |
| 62 | key-list | ||
| 63 | (string-to-list (make-string blocksize #x5c))))) | ||
| 64 | (i-key-pad (apply #'unibyte-string | ||
| 65 | (cl-map 'list #'logxor | ||
| 66 | key-list | ||
| 67 | (string-to-list (make-string blocksize #x36))))) | ||
| 68 | (inner (secure-hash algorithm (concat i-key-pad message) nil nil t))) | ||
| 69 | (secure-hash algorithm (concat o-key-pad inner) nil nil binary))) | ||
| 62 | (error "Unsupported hash algorithm %s" algorithm))) | 70 | (error "Unsupported hash algorithm %s" algorithm))) |
| 63 | 71 | ||
| 64 | (defconst base32-alphabet | 72 | (defconst base32-alphabet |
| @@ -81,10 +89,8 @@ string." | |||
| 81 | 89 | ||
| 82 | This is not a 100% faithful implementation of RFC 4648. The | 90 | This is not a 100% faithful implementation of RFC 4648. The |
| 83 | concept of encoding partial quanta is not implemented fully." | 91 | concept of encoding partial quanta is not implemented fully." |
| 84 | (unless (zerop (mod (length string) 8)) | ||
| 85 | (error "Padding is incorrect")) | ||
| 86 | (setq string (upcase string)) | 92 | (setq string (upcase string)) |
| 87 | (let* ((trimmed-array (append (string-trim-right string "=+") nil)) | 93 | (let* ((trimmed-array (string-trim-right string "=+")) |
| 88 | (hex (format "%X" (seq-reduce | 94 | (hex (format "%X" (seq-reduce |
| 89 | (lambda (acc char) (+ (ash acc 5) (aref base32-alphabet char))) | 95 | (lambda (acc char) (+ (ash acc 5) (aref base32-alphabet char))) |
| 90 | trimmed-array 0)))) | 96 | trimmed-array 0)))) |
| @@ -100,12 +106,12 @@ concept of encoding partial quanta is not implemented fully." | |||
| 100 | 106 | ||
| 101 | (defun totp (string) | 107 | (defun totp (string) |
| 102 | "Return a TOTP token using the secret hex STRING and current time." | 108 | "Return a TOTP token using the secret hex STRING and current time." |
| 103 | (let* ((key-bytes (totp--hex-decode-string (upcase string))) | 109 | (let* ((key-bytes (totp--hex-decode-string (upcase (base32-hex-decode string)))) |
| 104 | (counter (truncate (/ (time-to-seconds) 30))) | 110 | (counter (truncate (/ (time-to-seconds) 30))) |
| 105 | ;; we have to manually split the 64 bit number (u64 not supported in Emacs 27.2) | 111 | ;; we have to manually split the 64 bit number (u64 not supported in Emacs 27.2) |
| 106 | (counter-bytes (bindat-pack '((:high u32) (:low u32)) | 112 | (counter-bytes (bindat-pack '((:high u32) (:low u32)) |
| 107 | `((:high . ,(ash counter -32)) (:low . ,(logand counter #xffffffff))))) | 113 | `((:high . ,(ash counter -32)) (:low . ,(logand counter #xffffffff))))) |
| 108 | (mac (hmac 'sha1 key-bytes counter-bytes)) | 114 | (mac (hmac 'sha1 key-bytes counter-bytes t)) |
| 109 | (offset (logand (bindat-get-field (bindat-unpack '((:offset u8)) mac 19) :offset) #xf))) | 115 | (offset (logand (bindat-get-field (bindat-unpack '((:offset u8)) mac 19) :offset) #xf))) |
| 110 | (format "%06d" | 116 | (format "%06d" |
| 111 | (mod | 117 | (mod |
