More Examples: Talk notes

master
Mike Gerwitz 2019-03-17 12:14:22 -04:00
parent 444d9e87b9
commit 69738c3078
Signed by: mikegerwitz
GPG Key ID: 8C917B7F5DC51BA2
1 changed files with 407 additions and 28 deletions

View File

@ -180,17 +180,17 @@
| \_ Again: A Research Task | 0:00:15 | DRAFT | againframe |
| \_ A Quick-n-Dirty Solution | 0:01:10 | DRAFT | frame |
|-------------------------------------------------------+----------+---------+-------------|
| \_ More Examples | | LACKING | |
| \_ More Examples | | RAW | |
| \_ More Example Topics | | | |
| \_ Weather Every 60s | | LACKING | frame |
| \_ Resize Images | | LACKING | frame |
| \_ Password Generation | | LACKING | frame |
| \_ Password Manager | | LACKING | frame |
| \_ Remote Password Manager With 2FA | | LACKING | frame |
| \_ Taking Screenshots | | LACKING | frame |
| \_ Screenshot OCR | | LACKING | frame |
| \_ Full Circle | | LACKING | fullframe |
| \_ Getting Help | | LACKING | frame |
| \_ Weather Every 60s | | RAW | frame |
| \_ Resize Images | | RAW | frame |
| \_ Password Generation | | RAW | frame |
| \_ Password Manager | | RAW | frame |
| \_ Remote Password Manager With 2FA | | RAW | frame |
| \_ Taking Screenshots | | RAW | frame |
| \_ Screenshot OCR | | RAW | frame |
| \_ Full Circle | | RAW | fullframe |
| \_ Getting Help | | RAW | frame |
|-------------------------------------------------------+----------+---------+-------------|
| \_ Thank You | 00:00:01 | | fullframe |
#+END:
@ -2584,7 +2584,7 @@ This is certainly an efficient means of communicating with the machine.
We've come a long way from using the web browser and a mouse.
** LACKING More Examples
** RAW More Examples
*** More Example Topics [7/7] :noexport:
- [X] Screenshots with =import=.
- Including copying to clipboard.
@ -2601,7 +2601,7 @@ We've come a long way from using the web browser and a mouse.
- Use =tesserac= to detect matches from =Ctrl+F=.
- [X] Finding documentation with =info= and =man=.
*** LACKING Weather Every 60s :B_frame:
*** RAW Weather Every 60s :B_frame:
:PROPERTIES:
:BEAMER_env: frame
:END:
@ -2619,7 +2619,31 @@ Every 60.0s: weather | grep Temp... Sat Mar 16 23:18:56 2019
\_\ /_/
#+END_SRC
*** LACKING Resize Images :B_frame:
**** Notes :B_noteNH:
:PROPERTIES:
:BEAMER_env: noteNH
:END:
Now that we've put that research task to rest,
let's look at some more diverse examples.
This one,
for example.
It uses =watch= to execute a command every sixty seconds.
Specifically,
it uses =weather= to look up some information about the current weather
and grabs the temperature line.
=cut= is a command we haven't seen yet---it
grabs a field separated by the given delimiter.
The line is ``Temperature: temp'',
so that has the effect of stripping off the ``temperature:'' prefix.
And then figlet is a fun little tool that formats text like ASCII art,
with various fonts available.
Though I shold note that the source that =weather= gets its data from does
not update every sixty seconds.
*** RAW Resize Images :B_frame:
:PROPERTIES:
:BEAMER_env: frame
:END:
@ -2633,7 +2657,26 @@ $ for img in *.png; do
$ find . -name '*.png' -exec convert {} -resize 50% sm-{} \;
#+END_SRC
*** LACKING Password Generation :B_frame:
**** Notes :B_noteNH:
:PROPERTIES:
:BEAMER_env: noteNH
:DURATION: 00:00:35
:END:
This example will be useful to people who have a lot of images that the want
to perform an operation on.
ImageMagick has a =convert= tool which can do a huge variety of image
manipulations that you would expect to have to use, say, GIMP for.
In this case,
we're just using one of the simples ones to reduce the image size by 50%.
The first example uses /globbing/ to find all PNG images in the current
directory.
The second example uses the =find= command and searches all child
directories as well.
Both examples produce a new set of images prefixed with =sm-=.
*** RAW Password Generation :B_frame:
:PROPERTIES:
:BEAMER_env: frame
:END:
@ -2652,7 +2695,31 @@ $ cut -f2 eff_large_wordlist.txt \
oppressor roman jigsaw unhappy thinning grievance
#+END_SRC
*** LACKING Password Manager :B_frame:
**** Notes :B_noteNH:
:PROPERTIES:
:BEAMER_env: noteNH
:END:
How about password generation?
=pwgen= is a tool that can generate passwords of various forms.
Here we generate a random 32-character password.
That type of password is useful if you have a password manager,
but it's not useful if you need to memorize it.
When memorization is needed,
a /passphrase/ may be a better option.
A common way to generate those is to use a large list of memorable words and
choose them /at random/.
Diceware is one such system,
and the EFF has its own word list.
But we don't need physical dice when we can just use =sort= to randomly
permute the word list.
The EFF recommends taking at least six words,
which is what I did here.
This one is particularly memorable and morbid-sounding.
I'm a little upset that I put it in the slide instead of using it!
*** RAW Password Manager :B_frame:
:PROPERTIES:
:BEAMER_env: frame
:END:
@ -2677,7 +2744,63 @@ $ gpg --decrypt password-db.gpg \
#+END_SRC
#+BEAMER: \end{uncoverenv}
*** LACKING Remote Password Manager With 2FA :B_frame:
**** Notes :B_noteNH:
:PROPERTIES:
:BEAMER_env: noteNH
:END:
Speaking of password managers.
We can create a pretty decent rather quickly.
Let's say we have a password list encrypted using GnuPG,
which can be decrypted like so.
Each account has a URL,
username,
and password.
We pipe the output to =grep= to find the one we're looking for.
The caret anchors the match to the beginning of the line.
=-A2= instructs =grep= to return the line the matches /and/ the two lines
that follow it.
We then use =tail= to keep only the last two lines,
discarding the URL.
For each line,
we then read the first word into =key= and the rest of the line into
=value=.
This is where it gets a bit more interesting.
We don't want to actually output our password anywhere where others could
see it or where it may be vulnerable to a side channel like Van Eck
phreaking.
Instead,
we're going to copy the value to the clipboard.
But that has its own risks too.
What if there's a malicious program monitoring the clipboard for passwords?
I used =-l 1= with =xclip=.
=-l= stands for ``loop'',
which is the number of times to serve paste requests.
Normally =xclip= goes into the background and acts as a server.
=-quiet= keeps =xclip= in the foreground.
So if we see that the script moves on to request pasting the next value
before we've actually pasted it,
then we'll be made aware that something is wrong and perhaps we should
change our account information.
Another nice consequence is that we can paste the username in a field in the
web browser,
for example,
and then it'll immediately proceed to the next line of the password
database and prompt us to paste that.
So the first value you paste will be the username,
and the second value will be the password.
And then the script will exit.
Very convenient!
Since the decrypted data exist only as part of the pipeline,
the decrypted passwords are only kept plaintext in memory for the duration
of the script.
*** RAW Remote Password Manager With 2FA :B_frame:
:PROPERTIES:
:BEAMER_env: frame
:END:
@ -2692,7 +2815,58 @@ $ gpg --decrypt password-db.gpg \
$ ssh -Y mikegerwitz-pc get-passwd https://foo.com
#+END_SRC
*** LACKING Taking Screenshots :B_frame:
**** Notes :B_noteNH:
:PROPERTIES:
:BEAMER_env: noteNH
:END:
But what if you need passwords on multiple devices?
Well,
then you have to worry about how to keep them in sync.
It also means that,
if you are travelling and asked to decrypt files on your laptop,
for example,
you're put in a tough spot.
Instead,
let's make that command line from the previous slide a script called
=get-passwd=,
and have it take the URL as an argument.
We can then access it remotely over SSH.
But to have clipboard access,
we need to forward our X11 session,
which is what =-Y= does.
But that's still not good enough for me.
What if my master password is compromised---the
password for my database?
I'd rather have two-factor authentication.
I symmetrically encrypt my password database using a private key that's
stored on my Nitrokey,
which is a smart card---keys
cannot be extracted from it,
unless there's a vulnerabilty of course.
To unlock the card,
I must enter a PIN.
That's both something I know and something I have.
If you enter the PIN incorrectly three times,
the PIN needs to be reset with an administrative password.
If you get that wrong three times,
the device bricks itself.
And this all works over SSH too.
Encrypting long-term secrets with asymmetric keys isn't a great idea,
so there's a tradeoff.
I choose to accept it,
because passwords aren't long-term secrets---I
can easily change them.
But you could easily do both---
first require decryption with your smart card and then enter a passphrase
for a symmetric key.
*** RAW Taking Screenshots :B_frame:
:PROPERTIES:
:BEAMER_env: frame
:END:
@ -2708,7 +2882,36 @@ $ import -pause 5 -window root ss.png
import png:- | xclip -i -selection clipboard -t image/png
#+END_SRC
*** LACKING Screenshot OCR :B_frame:
**** Notes :B_noteNH:
:PROPERTIES:
:BEAMER_env: noteNH
:END:
Okay,
back to something less serious.
ImageMagick also comes with a vaguely-named utility called =import=,
which can capture images from an X server.
Screenshots.
If you run it with just a filename,
then it'll change your cursor to a cross.
You can drag to define a rectangular region to copy,
or you can just click on a window to take a screenshot of the whole thing.
The second example pauses for five seconds and then takes a screenshot of
the entire X session,
which includes all monitors.
I used this to take a screenshot of context menus in IceCat,
since the first method doesn't work in that case.
The final example avoids outputting to a file entirely and instead feeds
the raw image data to standard out.
We then pipe that to =xclip= to copy it to the clipboard.
Notice the new =image/png= type there.
Now you can paste the image into other programs,
like image editors or websites.
*** RAW Screenshot OCR :B_frame:
:PROPERTIES:
:BEAMER_env: frame
:END:
@ -2748,15 +2951,58 @@ $ xclip -o -selection clipboard -t image/png \
#+END_SRC
#+BEAMER: \end{onlyenv}
*** LACKING Full Circle :B_fullframe:
**** Notes :B_noteNH:
:PROPERTIES:
:BEAMER_env: noteNH
:DURATION: 00:01:10
:END:
But when I was trying to come up with interesting examples for this talk,
I wanted to try something I hadn't before.
=tesseract= is a free (as in freedom) optical character recognition
program.
Since =import= lets us select a region of the screen,
what if we used that to create a script that runs OCR on whatever we
select?
And just for fun,
what if the translation was presented to us by a cow?
In this example,
I selected the keynote speaker image on the LP2019 website.
It worked quite well.
But a cow isn't practical.
Instead,
you can imagine maybe binding this to a key combination in your window
manager.
In that case,
maybe it'd be more convenient if it was spoken to you,
like the second example.
Or maybe copied to your clipboard.
In the third example,
we take an image off of the clipboard,
run OCR,
and then display the resulting text in a GUI dialog with =zenity=.
I really like these examples,
because to an average user,
all of this seems somewhat novel.
And yet,
it's one of the simplest examples we've done!
YMMV with tesseract,
depending on your settings and training data.
*** RAW Full Circle :B_fullframe:
:PROPERTIES:
:BEAMER_env: fullframe
:END:
#+BEGIN_SRC sh
$ xdotool search --name ' GNU IceCat$' windowactivate --sync \
&& xdotool getactivewindow windowsize 1024 600 \
key ctrl+t \
windowsize 1024 600 \
key ctrl+t \
&& while read url; do
xdotool getactivewindow \
key ctrl+l type "$url" \
@ -2771,28 +3017,161 @@ $ xdotool search --name ' GNU IceCat$' windowactivate --sync \
done < url-list | tee results.txt
#+END_SRC
*** LACKING Getting Help :B_frame:
**** Notes :B_noteNH:
:PROPERTIES:
:BEAMER_env: noteNH
:END:
Okay,
for this final example,
I'm going to do something a bit more complex.
Please take a few seconds to look at this.
<pause>
Would anyone like to tell me what you think this command line does?
<...allocate extra time to this slide...>
=xdotool= is a swiss army knife of X11 operations.
It can find windows,
give them focus,
send keystrokes,
move the mouse,
and do many other things.
The first line here finds the first window ending in ``GNU IceCat'' and
gives it focus.
=--sync= blocks until that completes so we don't proceed too hastily.
We then proceed to resize it to 1024x600,
and then open a new tab by sending =Ctrl+T=.
That's right.
We've come full circle back to the web browser.
We then proceed to read each URL form a file =url-list=,
which you can see after =done=.
For each URL,
we send =Ctrl+L= to give focus to the location bar and then type in the
URL.
We can't chain any commands in =xdotool= after =type=,
which is why we have another invocation to hit =Return=.
We then sleep for five seconds to give time to navigate.
I use Tor,
so latency varies.
We then send =Ctrl+F=,
wait very briefly to give IceCat time to trigger the find,
and then send our string to search for.
If you remember,
I mentioned that part of the problem with the GUI approach is that it
requires visual inspection.
Fortunately for us,
we have =tesseract=!
So we take a screenshot of the IceCat window at the offset where the match
results are on my system.
We pipe that image to =tesseract= and,
if it contains the word ``Phrase'',
as in ``Phrase not found'',
we echo the URL as a non-match.
All of this is =tee='d to =results.txt= like before.
<demo it? FSF laptop likely has abrowser, so some tweaking will be needed.>
This is /not/ what I had in mind when I talked about melding mind and
machine.
But this shows that,
even with GUIs,
we can produce some level of automation using existing tools and a little
bit of creativity.
Of course,
this may not work on your system if you font size is different or because
of various other factors;
to generalize this,
we'd have to get more creative to find the result text.
It's also worth mentioning that =xdotool= can come in handy for the password
manager too---instead
of copying to the clipboard,
we can type it directly into a window.
And by specifying which window to send it to,
we can ensure that we don't accidentally type in the wrong window,
like a chat,
if the user changes focus.
That also thwarts systems that implement the terrible anti-pattern of try to
prevent you from pasting passwords.
*** RAW Getting Help :B_frame:
:PROPERTIES:
:BEAMER_env: frame
:END:
- All GNU packages have Info manuals
- All GNU packages have Info manuals and =--help=
- Most programs (including GNU) have manpages
#+BEAMER: \subskip
#+BEGIN_SRC sh
# manpage for grep
$ man grep
# full manual for grep
$ info grep
$ grep --help # usage information for grep
$ man grep # manpage for grep
$ info grep # full manual for grep
# bash help
$ help
$ man bash
#+END_SRC
**** Notes :B_noteNH:
:PROPERTIES:
:BEAMER_env: noteNH
:DURATION: 00:01:45
:END:
I have presented a lot of stuff here,
and I only got to a fraction of what I would have liked to talk about.
Some of you watching this aren't familiar with a lot of these topics,
or possibly /any/ of them,
so getting started may seem like a daunting task.
Where do you start?
As I showed before,
the process of writing a command line is an iterative one.
Learning is the same way.
I don't remember all of the options for these programs.
=xdotool= I had used only lightly before this talk,
for example;
I had to research how to write that command line.
But I didn't use the Internet to do it;
I did it from the comfort of my terminal using only what was already
installed on my system.
You can usually get usage information for programs by typing =--help= after
the command.
This will work for all GNU programs,
but not all command line programs implement it.
=tesseract=, for example, outputs its usage information when you run it with
no arguments,
but offers no =--help=.
All GNU programs also offer Info manuals,
which read like books;
those can be found with the =info= command,
and can also be read in a much better format using Emacs.
You can also usually find them online in HTML format.
Finally,
most command line programs for Unix-like operating systems also include
manpages,
accessible with the =man= command.
If you want to know how to use =man=,
you can view its own manpage using =man man=.
You can also get some help using Bash itself by simply typing =help= to list
its builtins,
and it has a very comprehensive manpage.
This is obviously a bit different than how people interact with GUIs,
which are designed to be discoverable without the need for users to read
documentation.
** Thank You :B_fullframe:
:PROPERTIES:
:BEAMER_env: fullframe