[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Let us see how to encrypt with Emacs?

From: Jean Louis
Subject: Re: Let us see how to encrypt with Emacs?
Date: Fri, 9 Jul 2021 15:27:29 +0300
User-agent: Mutt/2.0.7+183 (3d24855) (2021-05-28)

I am thinking to have it simpler for practical purposes, so here
is what I made now:

(defun pad-to-multiple-bytes (string max)
  "Return string padded to multiple of MAX bytes."
  (let* ((bytes (string-bytes string))
         (multiple (truncate (/ bytes max)))
         (multiple (if (zerop multiple) max (* (1+ multiple) max))))
    (string-pad string multiple)))

(defun rcd-encrypt-chacha20-64 (string password)
  "Encrypt STRING with PASSWORD by using CHACHA20-64 cipher."
  (let* ((key (pad-to-multiple-bytes password 32))
         (iv (substring (gnutls-hash-digest "SHA512" password) 0 15))
         (iv (pad-to-multiple-bytes iv 16))
         (string (pad-to-multiple-bytes string 64)))
    (car (gnutls-symmetric-encrypt "CHACHA20-64" key iv string))))

(rcd-encrypt-chacha20-64 "Some text here" "123Mypassword123") ⇒ 

(defun rcd-decrypt-chacha20-64 (encrypted-string password)
  "Decrypt ENCRYPTED-STRING with PASSWORD by using CHACHA20-64 cipher.

The return string will be trimmed."
  (let* ((key (pad-to-multiple-bytes password 32))
         (iv (substring (gnutls-hash-digest "SHA512" password) 0 15))
         (iv (pad-to-multiple-bytes iv 16))
         (decrypted (gnutls-symmetric-decrypt "CHACHA20-64" key iv 
         (decrypted (string-trim (car decrypted))))

(rcd-decrypt-chacha20-64 (rcd-encrypt-chacha20-64 "Some text here" 
"123Mypassword123") "123Mypassword123") ⇒ "Some text here"

As that is more practical function.

And maybe making a more generic function would be helpful. 

For generci function I wonder if the function `gnutls-cipers'
really yields alist or not, I am not sure, but this below seem to

(alist-get 'RC2-40 (gnutls-ciphers)) ⇒ (:cipher-id 17 :type 
gnutls-symmetric-cipher :cipher-aead-capable nil :cipher-tagsize 0 
:cipher-blocksize 8 :cipher-keysize 5 :cipher-ivsize 8)

Then result yields basically plist:

(plist-get (alist-get 'RC2-40 (gnutls-ciphers)) :cipher-id) ⇒ 17

Then I have the generic function that will satisfy my needs:

(defun rcd-encrypt-decrypt (enc-dec password &optional decrypt cipher digest)
  "Encrypt or decrypt ENC-DEC wi PASSWORD.

Default cipher is CHACHA20-64 or CIPHER as defined by the
function `gnutls-ciphers'. 

Default digest is SHA512 or HASH as defined by the function

Function encrypts by default, with DECRYPT being anything but
NIL, it will decrypt the ENC-DEC. "
  (let* ((cipher (or cipher "CHACHA20-64"))
         (cipher-plist (alist-get cipher (gnutls-ciphers) nil nil 'string=))
         (cipher-key-size (plist-get cipher-plist :cipher-keysize))
         (key (pad-to-multiple-bytes password cipher-key-size))
         (digest (or digest "SHA512"))
         (hash (gnutls-hash-digest digest password))
         (iv-size (plist-get cipher-plist :cipher-ivsize))
         (iv (substring hash 0 iv-size))
         (iv (string-pad iv iv-size))
         (block-size (plist-get cipher-plist :cipher-blocksize))
         (enc-dec (if decrypt enc-dec (pad-to-multiple-bytes enc-dec 
    (if decrypt
        (string-trim (car (gnutls-symmetric-decrypt cipher key iv enc-dec)))
      (car (gnutls-symmetric-encrypt cipher key iv enc-dec)))))

(rcd-encrypt-decrypt "My string here" "My password 123") ⇒ 

(rcd-encrypt-decrypt (rcd-encrypt-decrypt "My string here" "My password 123") 
"My password 123" t) ⇒ "My string here"

Now I come to what I really need, that is to encrypt and encode by base64 

(defun rcd-encrypt-decrypt-base64 (enc-dec password &optional decrypt cipher 
digest no-line-break)
  "Use base64 encoding and decoding with encryption."
  (let* ((enc-dec (if decrypt (base64-decode-string enc-dec) enc-dec))
         (enc-dec (rcd-encrypt-decrypt enc-dec password decrypt cipher digest))
         (enc-dec (if decrypt enc-dec (base64-encode-string enc-dec 

(rcd-encrypt-decrypt-base64 "My string" "MyPassword987" nil nil nil t) ⇒ 

 "MyPassword987" t) ⇒ "My string"

As that I can pass to the URL for Double Opt-In purposes instead
revealing the information to the public. Then I can even put
whole Emacs hash into the URL:

(setq hash (make-hash-table))
(puthash "MID" 123 hash)
(puthash "EID" 98 hash)
(puthash "CID" 333 hash)
(puthash "redirect" ""; hash)

hash ⇒ #s(hash-table size 65 test eql rehash-size 1.5 rehash-threshold 0.8125 
data ("MID" 123 "CID" 333 "EID" 98 "redirect" "";))

(rcd-encrypt-decrypt-base64 (prin1-to-string hash) "MyPassword987" nil nil nil 
t) ⇒ 

And use that to subscribe users, unsubscribe and similar with
more safety that users will not abuse my system.


Take action in Free Software Foundation campaigns:

In support of Richard M. Stallman

reply via email to

[Prev in Thread] Current Thread [Next in Thread]