unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
From: Jean Louis <bugs@gnu.support>
To: Eli Zaretskii <eliz@gnu.org>
Cc: help-gnu-emacs@gnu.org
Subject: Re: Let us see how to encrypt with Emacs?
Date: Fri, 9 Jul 2021 15:27:29 +0300	[thread overview]
Message-ID: <YOhAsYBSHIb24EN4@protected.localdomain> (raw)
In-Reply-To: <83mtqvdb4s.fsf@gnu.org>

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") ⇒ "\352\200\333\2460\246\330\x1c\211P\311\207\260m\211R\x0eD0\222\237\200K=\216\214\267\320p\273\x1a>,\x7fT\262 k\361\336;i\336I\325\x0fXi\200^[G\325\303\x01\x15\x7f\312\320\x17\254D\x1cg9"

(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 encrypted-string))
	 (decrypted (string-trim (car decrypted))))
    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
work:

(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
`gnutls-digests'.

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 block-size))))
    (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") ⇒ "\273/\322Xk_m@\372a\323\x1d\257\317\330\301\263\224\220\351\303>\241\245\a[\344\226\203;\f-\244\265\331\263\253\354\230\206\x05\3140\221\341\370\361&\333\317\357T?(\302#\206&\355\x01\x04\x01~\200"

(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 method:

(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 no-line-break))))
    enc-dec))

(rcd-encrypt-decrypt-base64 "My string" "MyPassword987" nil nil nil t) ⇒ "XOxgVUXurXzqWP9y5pzs6IwjWafdG6sWcqVz13HzfYhnWLiDn3/yo8DuMnrTuIjCC9BEyAxqW7dmAt9h0bwKoA=="

(rcd-encrypt-decrypt-base64 "XOxgVUXurXzqWP9y5pzs6IwjWafdG6sWcqVz13HzfYhnWLiDn3/yo8DuMnrTuIjCC9BEyAxqW7dmAt9h0bwKoA==" "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" "https://www.example.com" 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" "https://www.example.com"))

(rcd-encrypt-decrypt-base64 (prin1-to-string hash) "MyPassword987" nil nil nil t) ⇒ "MuZoTlDvrD/5Gb0+o5y/odZmWbHIG/9TIfFzkiC/fdoiEPnQ13Kh6pqrMmvdrYiQTpgFm0RnD/80R4wpnvBOoKGtDWQnpv/5191ZzmNRmNDBDLJdG/f/Iv9VR0LmieP38cvWtZ3uxGWZdsaWCBhtsqDDYFrTS6mrPXmmyGE4hjedt3Z9E9cDOStlgiS+ynwwmlhNJf0Jga5848y/I+To2+zp3qw9Z+KiOhq+Vr2Mpm8/6zFQ9YxuDZNy9LWjJL/L"

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


Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns

In support of Richard M. Stallman
https://stallmansupport.org/



      parent reply	other threads:[~2021-07-09 12:27 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-09  7:38 Let us see how to encrypt with Emacs? Jean Louis
2021-07-09 10:39 ` Eli Zaretskii
2021-07-09 11:32   ` Jean Louis
2021-07-09 11:52     ` tomas
2021-07-09 12:35       ` Jean Louis
2021-07-09 12:43         ` tomas
2021-07-09 11:55     ` Eli Zaretskii
2021-07-09 12:28       ` Jean Louis
2021-07-09 12:53         ` Eli Zaretskii
2021-07-09 12:27   ` Jean Louis [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=YOhAsYBSHIb24EN4@protected.localdomain \
    --to=bugs@gnu.support \
    --cc=eliz@gnu.org \
    --cc=help-gnu-emacs@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).