commit 4b26e132113a30d1b54bcf8b47c919ba71e23cb8
parent c6ee274013a64c0b8155fd0d6d694fe5fcb5cf1b
Author: Vineet Kumar <git@vineetk.net>
Date: Sat, 6 Jun 2026 13:53:44 -0400
fix totp with secrets that need padding
Diffstat:
2 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/kasi-totp.el b/kasi-totp.el
@@ -55,10 +55,18 @@ string."
(when (> (length key) blocksize)
(setq key (secure-hash algorithm key)))
(when (< (length key) blocksize)
- (setq key (concat key (make-string (- blocksize (length key)) 0))))
- (let ((o-key-pad (cl-map 'string #'logxor key (make-string blocksize #x5c)))
- (i-key-pad (cl-map 'string #'logxor key (make-string blocksize #x36))))
- (secure-hash algorithm (concat o-key-pad (secure-hash algorithm (concat i-key-pad message) nil nil t)) nil nil binary)))
+ (setq key (string-as-unibyte (concat key (make-string (- blocksize (length key)) 0)))))
+ (let* ((key-list (string-to-list key))
+ (o-key-pad (apply #'unibyte-string
+ (cl-map 'list #'logxor
+ key-list
+ (string-to-list (make-string blocksize #x5c)))))
+ (i-key-pad (apply #'unibyte-string
+ (cl-map 'list #'logxor
+ key-list
+ (string-to-list (make-string blocksize #x36)))))
+ (inner (secure-hash algorithm (concat i-key-pad message) nil nil t)))
+ (secure-hash algorithm (concat o-key-pad inner) nil nil binary)))
(error "Unsupported hash algorithm %s" algorithm)))
(defconst base32-alphabet
@@ -81,10 +89,8 @@ string."
This is not a 100% faithful implementation of RFC 4648. The
concept of encoding partial quanta is not implemented fully."
- (unless (zerop (mod (length string) 8))
- (error "Padding is incorrect"))
(setq string (upcase string))
- (let* ((trimmed-array (append (string-trim-right string "=+") nil))
+ (let* ((trimmed-array (string-trim-right string "=+"))
(hex (format "%X" (seq-reduce
(lambda (acc char) (+ (ash acc 5) (aref base32-alphabet char)))
trimmed-array 0))))
@@ -100,12 +106,12 @@ concept of encoding partial quanta is not implemented fully."
(defun totp (string)
"Return a TOTP token using the secret hex STRING and current time."
- (let* ((key-bytes (totp--hex-decode-string (upcase string)))
+ (let* ((key-bytes (totp--hex-decode-string (upcase (base32-hex-decode string))))
(counter (truncate (/ (time-to-seconds) 30)))
;; we have to manually split the 64 bit number (u64 not supported in Emacs 27.2)
(counter-bytes (bindat-pack '((:high u32) (:low u32))
`((:high . ,(ash counter -32)) (:low . ,(logand counter #xffffffff)))))
- (mac (hmac 'sha1 key-bytes counter-bytes))
+ (mac (hmac 'sha1 key-bytes counter-bytes t))
(offset (logand (bindat-get-field (bindat-unpack '((:offset u8)) mac 19) :offset) #xf)))
(format "%06d"
(mod
diff --git a/kasi.el b/kasi.el
@@ -86,7 +86,7 @@ Two %s are needed for password and username for now."
(defun kasi--totp (file)
"Returns current TOTP code from secret file."
(let* ((totp-secret (kasi--get file 'totp))
- (totp-code (totp (base32-hex-decode totp-secret))))
+ (totp-code (totp totp-secret)))
(kill-new totp-code)
(message (format "TOTP %s for %s copied to kill ring"
totp-code