summaryrefslogtreecommitdiff
path: root/kasi-totp.el
diff options
context:
space:
mode:
authorVineet Kumar <git@vineetk.net>2026-06-06 13:53:44 -0400
committerVineet Kumar <git@vineetk.net>2026-06-06 13:53:44 -0400
commit4b26e132113a30d1b54bcf8b47c919ba71e23cb8 (patch)
treef3496e89b2fd4fb171b8e144b4c25ddc194994be /kasi-totp.el
parentc6ee274013a64c0b8155fd0d6d694fe5fcb5cf1b (diff)
fix totp with secrets that need paddingHEADv1.2master
Diffstat (limited to 'kasi-totp.el')
-rw-r--r--kasi-totp.el24
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
82This is not a 100% faithful implementation of RFC 4648. The 90This is not a 100% faithful implementation of RFC 4648. The
83concept of encoding partial quanta is not implemented fully." 91concept 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