Parole aleatoare în Linux, “extended ASCII”

Deși în teorie problema din titlu este una rezolvată, în practică de multe ori mi-am dorit o parolă de o complexitate mai mare față de ce-mi oferă majoritatea uneltelor ce nu ies din standard ASCII. Prin metoda subsemnatului, se ia următoarea funcție și se trântește în .bashrc:

function urandompass()
{
	cat /dev/urandom | tr -dc '[\41-\176\241-\254\256-\376]' | fold -w $1 | head -n 1
}

Apelul este cretin de simplu: urandompass 12 va genera o parolă de 12 caractere. Sau cheie, am zis-o și pe asta. Funcția poate fi folosită pentru a genera chei pentru un “block cipher”.

Cu toate acestea, pentru cei cu terminalul setat pe UTF-8, caracterele dincolo de range-ul celui de-al 7-lea bit (aka cele ce intră în extended ASCII) nu vor fi printate corect. Teoria spune faptul că UTF-8 este compatibil doar cu setul ASCII, ăla standard. În prealabil este nevoie să se seteze terminalul pe un char encoding single-byte ce implementează vreo formă de extended ASCII gen ISO-8859-x, unde x = 1 este Western, x = 2 = Central European, etc. Personal prefer Western. Pentru cei cu Gnome Terminal, “Terminal » Set Character Encoding » Add or Remove …” dacă e pentru prima dată, dacă nu, atunci ar trebui să poată fi ales din meniu un encoding diferit de cel implicit. Buba este faptul că Gnome Terminal are memorie destul de proastă deci va da reset la UTF-8 dacă terminalul este închis sau se execută reset, deci operația trebuie repetată înainte de a genera orice parolă / cheie.

Acum urmează partea pentru obsedații de detalii aka cei după chipul și asemănarea subsemnatului. “Limitarea” la extended ASCII, ce oricum oferă o complexitate mai bună decât majoritatea generatoarelor, provine de fapt din tr. Un info coreutils ‘tr invocation’ în shell specifică destul de clar: “Currently `tr’ fully supports only single-byte characters.”, deci suportă multi-byte din jumătatea lui cinci. Pentru amatorii de detalii, acele range-uri din funcția mea au fost documentate, oarecum, în prealabil.

În DEC:

33-126
161-172
174-254

În OCT:

41-176
241-254
256-376

Evident, cu ochiul liber se poate vedea că tr primește octal, precum zice manualul. Pentru a le determina am încercat cu encoding ISO-8859-1 și ISO-8859-2 o aplicație ce printează tot range-ul single-byte (mă rog, fără ultimul caracter).

Pentru PHP-iști:

for ($i = 0; $i < 256; $i++)
{
	echo $i.': '.chr($i)."\n";
}

Iar pentru snobii cu C, avem alternativă 😀 :

#include 
 
int main()
{
        for (int i = 0; i < 256; i++)
        {
                printf("%d: %c\n", i, i);
        }
        return 0;
}

gcc -std=c99 -o chars chars.c

Inițial m-am inspirtat dintr-o versiune *sh de pe linuxquestions.org, dar arată cretin, nu dau paste la așa ceva. Mă cam strânge octalul de dinți. O versiune rescrisă pentru DEC junkies:

#!/bin/bash
 
chr()
{
	printf \\$(printf '%03o' $1)
}
 
i=0
while [ $i -lt 256 ]; do
	echo "$i: `chr $i`"
	let "i++"
done

Pentru cei ce preferă alte encoding-uri single-byte, dacă range-urile de mai sus nu sunt potrivite, atunci se poate rula oricând vreo aplicație de mai sus pentru a face un test de char printing.

Pentru cei ce nu s-au născut cu “DEC to OCT converter” în cap, așa ca subsemnatul, Calculator din Gnome (gcalctool) are și un mod Programming (Ctrl+P).