[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") ⇒
"\352\200\333\2460\246\330\211P\311\207\260m\211RD0\222\237\200K=\216\214\267\320p\273>,T\262
k\361\336;i\336I\325Xi\200G\325\303\312\320\254Dg9"
(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\257\317\330\301\263\224\220\351\303>\241\245[\344\226\203;
-\244\265\331\263\253\354\230\206\3140\221\341\370\361&\333\317\357T?(\302#\206&\355~\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/
Re: Let us see how to encrypt with Emacs?,
Jean Louis <=