From 4b26e132113a30d1b54bcf8b47c919ba71e23cb8 Mon Sep 17 00:00:00 2001 From: Vineet Kumar Date: Sat, 6 Jun 2026 13:53:44 -0400 Subject: fix totp with secrets that need padding --- kasi-totp.el | 24 +++++++++++++++--------- kasi.el | 2 +- 2 files changed, 16 insertions(+), 10 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." (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 index d4c884b..7817c8c 100644 --- 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 -- cgit v1.2.3