2

I'm writing a bash script with the following snippet:

#!/bin/bash

# usage '$bash this-script.sh in.pdf out.pdf'

 stty -echo
 printf "Password: "
 read password
 stty echo
 echo

 pdfencrypt "$1" -p "$password" -o "$2"

on characters like § ä ö ü it fails with the following message:

incompatible character encodings: UTF-8 and ASCII-8BIT

Am I encountering a bug of pdfencrypt or is the example not coded correctly?
If I use echo "$password" all is going well.

  • You don't need stty; you can use read -s instead. – Hauke Laging Aug 5 '17 at 22:30
  • 2
    Does an export LC_ALL=C at the beginning provide a fix for your encoding issue? BTW, your first block can be substituted with read -s -r -p "Password: " password; echo and you must be warned that read var trims space (IFS actually) characters. You probably should execute read -r and use the $REPLY variable. – xhienne Aug 5 '17 at 22:34
  • 2
    Are you sure that pdfencrypt can handle UTF-8 input? If not then you should save future pain and omit umlauts. If it is really necessary then you may use iconv to convert the UTF-8 string to e.g. latin1 before passing it to pdfencrypt. Then you probably have to change the character set variable, too: LANG=de_DE.latin1 pdfencrypt ... – Hauke Laging Aug 5 '17 at 22:43
  • @xhienne wow thanks, yes it does. Seems to be fixed. If you post that as an answer it is as much as accepted! Though I would be interested in why and how this works. Also if you could explain in more detail what you mean with the $REPLY variable. – nath Aug 5 '17 at 22:44
  • @xhienne well, the encryption works but I can't decrypt it anymore. – nath Aug 5 '17 at 22:51
3

It seems that pdfencrypt requires an 8bit (ISO-8859) encoded password and does not know how to deal with (i.e. convert) UTF-8 passwords.

You must use a compatible character encoding when executing pdfencrypt, for encryption and decryption. Plain ASCII ("C") or ISO-8859-n (like "de_DE.latin1" as suggested by Hauke Laging) should work. In my opinion, that just instructs pdfencrypt to take the characters of your password as is (i.e. no conversion necessary), that's all.

Just add this line at the top of your script:

export LC_ALL=de_DE.latin1        # Or fr_FR, or latin15, or... Any valid locale for your system

Or changing this single line may be enough:

LC_ALL=de_DE.latin1 pdfencrypt "$1" -p "$password" -o "$2"

Do the same for the decoding.

If you convert your password with iconv instead of setting LC_ALL, I guess you would have the same issue since pdfencrypt would still believe you are giving it UTF-8 characters when it encounters 8bit ones.

Anyway, to make things easier, you probably should stick to the 7bit ASCII character set: space, non-accented letters, digits, basic punctuation, etc. (man 7 ascii)

As for the space, you should be aware that reading into a specific variable with (read -r var) removes leading and trailing spaces (actually the characters in the shell variable IFS). That may be annoying for a password. You should use read -r which put the entire line read into the REPLY variable.

That would give that code:

export LC_ALL=de_DE.latin1
read -r -s -p "Password: "
echo
pdfencrypt "$1" -p "$REPLY" -o "$2"
  • Hey 100x THANKS; really nice. Only have one Up-vote. I did not know I could use $REPLY instead of read -r var seems like this is gold in this case. export LC_ALL=de_DE.latin1 works as long as I use the same tool with the same setting for decryption. If I use GUI reader like evince I dit not get it working. But sticking to 7bit ASCII is going to be my first choice. I'm gonna read the man page now :-) Thanks! – nath Aug 5 '17 at 23:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.