(load (expand-file-name "../util" (file-name-directory (or load-file-name buffer-file-name)))) (require 'seq) (defun parse-profile (query) (mapcar (lambda (kv) (split-string kv "=")) (split-string query "&"))) (test-equal (parse-profile "foo=bar&baz=qux&zap=zazzle") '(("foo" "bar") ("baz" "qux") ("zap" "zazzle"))) (defun encode-profile (profile) (mapconcat (lambda (kv) (mapconcat 'identity kv "=")) profile "&")) (test-equal (encode-profile '(("foo" "bar") ("baz" "qux") ("zap" "zazzle"))) "foo=bar&baz=qux&zap=zazzle") (defun profile-for (email) (setq email (replace-regexp-in-string "[&=]" "" email)) (encode-profile `(("email" ,email) ("uid" "10") ("role" "user")))) (test-equal (profile-for "foo@bar.com") "email=foo@bar.com&uid=10&role=user") (setq key (random-bytes aes-128-key-size)) (defun encrypted-profile-for (email) (aes-128-ecb-encrypt (pkcs7pad (profile-for email)) key)) (defun test-user-profile (ciphertext) (let* ((plaintext (pkcs7unpad (aes-128-ecb-decrypt ciphertext key))) (profile (parse-profile plaintext))) (message "Email: %s" (cadr (assoc "email" profile))) (message "UID: %s" (cadr (assoc "uid" profile))) (message "Role: %s" (cadr (assoc "role" profile))))) ;; |email=email@foo.|adminPPPPPPPPPPP|bar&uid=10&role=| ;; |email=email@foo.|bar&uid=10&role=|adminPPPPPPPPPPP| (setq ciphertext (encrypted-profile-for (concat "email@foo.admin" (make-string 11 11) "bar"))) (setq blocks (seq-partition ciphertext aes-128-block-size)) (setq blocks (list (elt blocks 0) (elt blocks 2) (elt blocks 1))) (setq ciphertext (apply 'concat blocks)) (test-user-profile ciphertext)