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/
prev 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).