Ruby Semplice programma di criptaggio personalizzato

Stato
Discussione chiusa ad ulteriori risposte.

Tibor Drèvis

Utente Bronze
14 Febbraio 2015
33
9
4
42
Più per curiosità che per altro ho pensato sarebbe stato carino creare un programma di criptaggio per i messaggi e magari automatizzarlo etc. Ho scritto questi due codici in una mezz'oretta circa quindi cioé, può essere migliorato molto. Non sono riuscito a rendere criptabili anche i simboli, però mi sarebbe piaciuto parecchio, se avete qualche idea su come rendere questo programma un po' più fluido fatemelo sapere, so che ruby di norma è parecchio lento, ma questo l'ho trovato esagerato.


Qui di seguito l'encrypter:


Ruby:
puts("Seleziona la chiave personalizzata che vuoi utilizzare, e ricorda! Devono essere tutte le lettere dell'alfabeto, e non usare né numeri né simboli.")
p_key=gets.chomp.to_s
puts("============================================================================")
puts("Dopodiché inserisci il messaggio che vuoi criptare con la chiave selezionata")
msg=gets.chomp.to_s
msg=msg.downcase
alphabet="abcdefghijklmnopqrstuvwxyz"
encr_msg=""

for char in (0..msg.length-1)
    if (msg[char]==" ")
        encr_msg<< " "
    end
    for x in (0..alphabet.length-1)
        if (msg[char]==alphabet[x])
            encr_msg<<p_key[x]
        end
    end
end



puts(encr_msg)
puts("Non scordare la chiave per decriptare il messaggio: ", p_key)

e qui il decrypter:

Ruby:
print("Inserisci il messaggio che desideri descriptare: ")
encr_msg=gets.chomp.to_s
encr_msg=encr_msg.downcase
puts("Inserisci la chiave per decriptare il messaggio! E ricorda, solo lettere.")
p_key=gets.chomp.to_s
decr_msg=""
alphabet="abcdefghijklmnopqrstuvwxyz"

for char in (0..encr_msg.length-1)
    if (encr_msg[char]==" ")
        decr_msg << " "
    end
    for x in (0..p_key.length-1)
        if (encr_msg[char]==p_key[x])
            decr_msg<<  alphabet[x]
        end
    end
end

puts("Il messaggio decriptato è: ", decr_msg)

Fatemi anche sapere se potete se funziona alla perfezione!! Ho notato che a volte ripete qualche lettera, ma non sono sicuro se fosse dovuto alla chiave che ho scelto o altro.
 
Più per curiosità che per altro ho pensato sarebbe stato carino creare un programma di criptaggio per i messaggi e magari automatizzarlo etc. Ho scritto questi due codici in una mezz'oretta circa quindi cioé, può essere migliorato molto. Non sono riuscito a rendere criptabili anche i simboli, però mi sarebbe piaciuto parecchio, se avete qualche idea su come rendere questo programma un po' più fluido fatemelo sapere, so che ruby di norma è parecchio lento, ma questo l'ho trovato esagerato.


Qui di seguito l'encrypter:


Ruby:
puts("Seleziona la chiave personalizzata che vuoi utilizzare, e ricorda! Devono essere tutte le lettere dell'alfabeto, e non usare né numeri né simboli.")
p_key=gets.chomp.to_s
puts("============================================================================")
puts("Dopodiché inserisci il messaggio che vuoi criptare con la chiave selezionata")
msg=gets.chomp.to_s
msg=msg.downcase
alphabet="abcdefghijklmnopqrstuvwxyz"
encr_msg=""

for char in (0..msg.length-1)
    if (msg[char]==" ")
        encr_msg<< " "
    end
    for x in (0..alphabet.length-1)
        if (msg[char]==alphabet[x])
            encr_msg<<p_key[x]
        end
    end
end



puts(encr_msg)
puts("Non scordare la chiave per decriptare il messaggio: ", p_key)

e qui il decrypter:

Ruby:
print("Inserisci il messaggio che desideri descriptare: ")
encr_msg=gets.chomp.to_s
encr_msg=encr_msg.downcase
puts("Inserisci la chiave per decriptare il messaggio! E ricorda, solo lettere.")
p_key=gets.chomp.to_s
decr_msg=""
alphabet="abcdefghijklmnopqrstuvwxyz"

for char in (0..encr_msg.length-1)
    if (encr_msg[char]==" ")
        decr_msg << " "
    end
    for x in (0..p_key.length-1)
        if (encr_msg[char]==p_key[x])
            decr_msg<<  alphabet[x]
        end
    end
end

puts("Il messaggio decriptato è: ", decr_msg)

Fatemi anche sapere se potete se funziona alla perfezione!! Ho notato che a volte ripete qualche lettera, ma non sono sicuro se fosse dovuto alla chiave che ho scelto o altro.
Posta il codice su Pastebin.
 
Non so se hai iniziato Ruby da poco ma ci sono alcune cose, dal punto di vista stilistico che puoi migliorare:

1. for non viene usato, si usa invece each:

Codice:
(A..Z).each do |letter|
    puts letter
end

Inoltre, come hai visto dall'esempio precedente, Ruby permette di definire una lista delle lettere dell'alfabeto come un range (non c'è bisogno di scriverle una ad una).

2. Le parentesi intorno alla condizione del if non si mettono mai siccome non sono richieste.

3. Invece di 0..msg.length - 1 puoi fare:

Codice:
0.upto(message.size) do |index|
    # ...
end

Ti consiglio di guardarti qualche styleguide: https://github.com/bbatsov/ruby-style-guide
 
Sì, ero a conoscenza dell'each loop, avevo provato inizialmente ad usarlo perché mi sembrava più semplice, poi però ho cambiato idea perché per qualche ragione non mi riusciva, allora ho risalito la strada diciamo più ''ostica'' provando con i for loop, tenendo a mente che sarei riuscito facilmente anche a tradurlo in Python, perché più o meno era anche questo il mio scopo. Comunque sì, ho iniziato relativamente da poco, circa da 2 mesi con un tutor :)
 
  • Mi piace
Reazioni: TheSeeker
Sì, ero a conoscenza dell'each loop, avevo provato inizialmente ad usarlo perché mi sembrava più semplice, poi però ho cambiato idea perché per qualche ragione non mi riusciva, allora ho risalito la strada diciamo più ''ostica'' provando con i for loop, tenendo a mente che sarei riuscito facilmente anche a tradurlo in Python, perché più o meno era anche questo il mio scopo. Comunque sì, ho iniziato relativamente da poco, circa da 2 mesi con un tutor :)
Se devi tradurlo in Python tanto vale farlo in Python.

Comunque non era una critica eh, volevo solo farti notare come può migliorare :)

Ruby è un bellissimo linguaggio e non usare tutte le features che ti mette a disposizione è uno spreco.
 
PS: gets.chomp di default ritorna una stringa, il to_s è inutile.

Inviato dal mio ALE-L21 utilizzando Tapatalk
 
E' stato un consiglio del mio tutor, non avevamo molto tempo, ed il suo scopo principale era insegnarmi più concetti della programmazione "pura" possibile, in modo da essere versatile verso altri linguaggi di scripting, tuttavia ho anche imparato tranquillamente varie features e metodi carini solo disponibili su Ruby, come l'each loop il times loop, e sono davvero comodi! Quasi troppo oserei dire...
 
  • Mi piace
Reazioni: TheSeeker
Non so se hai iniziato Ruby da poco ma ci sono alcune cose, dal punto di vista stilistico che puoi migliorare:

1. for non viene usato, si usa invece each:

Codice:
(A..Z).each do |letter|
    puts letter
end

Inoltre, come hai visto dall'esempio precedente, Ruby permette di definire una lista delle lettere dell'alfabeto come un range (non c'è bisogno di scriverle una ad una).

2. Le parentesi intorno alla condizione del if non si mettono mai siccome non sono richieste.

3. Invece di 0..msg.length - 1 puoi fare:

Codice:
0.upto(message.size) do |index|
    # ...
end

Ti consiglio di guardarti qualche styleguide: https://github.com/bbatsov/ruby-style-guide

1. Il for viene pure utilizzato nel Ruby, ma l'each viene considerato il più peculiare al linguaggio. Considererei di utilizzare comunque l'each principalmente perchè l'indice è persistente solo in quella porzione del codice (nel contesto del loop).
2. Omettere le parentesi non fa nè caldo nè freddo. Io considererei di lasciarle stare.
3. Il tuo consiglio non migliorerebbe nulla, stai solo provando a rendere più elegante del codice inutilmente. Se fosse un po' troppo sporca la soluzione dal punto di vista di sintassi, allora passo a trovarmi un'alternativa che non cambi funzionalmente, ma il modo di scrivere il codice.
Ho notato che a volte ripete qualche lettera, ma non sono sicuro se fosse dovuto alla chiave che ho scelto o altro.

Non conosco il Ruby, prendi con le pinze ciò che stai per leggere.
Il problema molto probabilmente sta qui:
Ruby:
for char in (0..msg.length-1)
    if (msg[char]==" ")
        encr_msg<< " "
    end
    for x in (0..alphabet.length-1)
        if (msg[char]==alphabet[x])
            encr_msg<<p_key[x]
        end
    end
end
se io immettessi un numero nel testo da criptare, verrebbe crittato pure quello? A quanto pare vengono crittate solo le lettere alfabetiche (tra l'altro non capitalizzate). La lunghezza di p_key deve essere per forza proporzionale alla lunghezza del testo crittato?
 
1. Il for viene pure utilizzato nel Ruby, ma l'each viene considerato il più peculiare al linguaggio. Considererei di utilizzare comunque l'each principalmente perchè l'indice è persistente solo in quella porzione del codice (nel contesto del loop).
2. Omettere le parentesi non fa nè caldo nè freddo. Io considererei di lasciarle stare.
3. Il tuo consiglio non migliorerebbe nulla, stai solo provando a rendere più elegante il codice inutilmente. Se fosse un po' troppo sporca la soluzione dal punto di vista di sintassi, allora passo a trovarmi un'alternativa che non cambi funzionalmente, ma il modo di scrivere il codice.
Si hai assolutamente ragione, era solo per renderlo più elegante.
 
1. Il for viene pure utilizzato nel Ruby, ma l'each viene considerato il più peculiare al linguaggio. Considererei di utilizzare comunque l'each principalmente perchè l'indice è persistente solo in quella porzione del codice (nel contesto del loop).
2. Omettere le parentesi non fa nè caldo nè freddo. Io considererei di lasciarle stare.
3. Il tuo consiglio non migliorerebbe nulla, stai solo provando a rendere più elegante del codice inutilmente. Se fosse un po' troppo sporca la soluzione dal punto di vista di sintassi, allora passo a trovarmi un'alternativa che non cambi funzionalmente, ma il modo di scrivere il codice.


Non conosco il Ruby, prendi con le pinze ciò che stai per leggere.
Il problema molto probabilmente sta qui:
Ruby:
for char in (0..msg.length-1)
    if (msg[char]==" ")
        encr_msg<< " "
    end
    for x in (0..alphabet.length-1)
        if (msg[char]==alphabet[x])
            encr_msg<<p_key[x]
        end
    end
end
se io immettessi un numero nel testo da criptare, verrebbe crittato pure quello? A quanto pare vengono crittate solo le lettere alfabetiche (tra l'altro non capitalizzate). La lunghezza di p_key deve essere per forza proporzionale alla lunghezza del testo crittato?



Non è quello il problema, cioé, non riuscivo già da prima a criptare numeri e simboli, ma il problema non era quello, ho notato che a volte può capitare che alcune lettere vengano modificate a caso. p_key deve avere una lunghezza ben specifica, ma non ha nessuna correlazione con il messaggio criptato, deve essere abbastanza lungo da ospitare tutte le lettere dell'alfabeto, esattamente lunga quanto la variabile alphabet="abcdefghijklmnopqrstuvwxyz" , senza nessuna ripetizione di lettere.
 
Non è quello il problema
Non ho detto che il problema siano i numeri nel testo da criptare, la lunghezza di p_key, o la lunghezza del testo crittato. Io ho scritto chiaramente che il problema sta sicuramente in quel codice (che è davvero molto sicuro, dato che è la parte in cui critti il testo), il resto è un discorso a parte.

Non è quello il problema, cioé, non riuscivo già da prima a criptare numeri e simboli
Mi sembra ovvio che il problema sta nel fatto che il tuo charset non soddisfa qualsiasi tipo di input venga immesso dall'utente.

esattamente lunga quanto la variabile alphabet="abcdefghijklmnopqrstuvwxyz" , senza nessuna ripetizione di lettere.
L'avevo già capito che doveva avere una lunghezza ben precisa, difatti ti volevo comunque far capire che non puoi costringere all'utente di utilizzare quella specifica lunghezza e basta, è fastidioso tanto quanto buttarsi dei mattoni sui piedi.

Ti consiglierei di rivalutare il tuo codice, perchè dal punto di vista didattico è ok, in altro no.
 
Ho pubblicato il codice proprio per ricevere consigli, esponimi la tua soluzione!
I miei consigli sono già esposti: rendere l'utente in grado di personalizzare la sua chiave al 100% (pure nella lunghezza), refactoring del codice. Dovresti saper applicarli tu, io non ho conoscenze in Ruby e credo di aver dato il mio meglio.
Tralasciando il punto di vista didattico, a prescindere dal codice non si dovrebbe mai utilizzare un algoritmo crittografico non testato da analisti. Don't roll your own cryptography -> un mantra che chiunque con un minimo di conoscenza in crittografia conosce che dice di non fare quello che hai fatto.

p.s: il seguente codice nel tuo primo loop:
Ruby:
if (msg[char]==" ")
        encr_msg<< " "
    end
prosegue inutilmente anche se la condizione è vera. Tu non noterai niente, ma contemporaneamente fai un altro loop inutilmente pur sapendo che lo spazio non è presente nel tuo charset. Dovrebbe essere:
Ruby:
if (msg[char]==" ")
        encr_msg<< " "
        next
    end
per passare subito alla successiva iterazione.
 
p.s: il seguente codice nel tuo primo loop:
Ruby:
if (msg[char]==" ")
        encr_msg<< " "
    end
prosegue inutilmente anche se la condizione è vera. Tu non noterai niente, ma contemporaneamente fai un altro loop inutilmente pur sapendo che lo spazio non è presente nel tuo charset. Dovrebbe essere:
Ruby:
if (msg[char]==" ")
        encr_msg<< " "
        next
    end
per passare subito alla successiva iterazione.
O ancora meglio:
Ruby:
if msg[char] >= 'a' and msg[char] <= 'z'
  # codice per cifrare
else
  encr_msg << msg[char]
end
Che con una breve ricerca su google (non conosco ruby) vedo che si può anche scrivere in questo modo:
Ruby:
if alphabet.include? msg[char]
  # codce per cifrare
else
  encr_msg << msg[char]
end

Questo ti da il vantaggio di poter rappresentare anche le lettere non presenti in alphabet (eg. simbole e lettere maiuscole) e di poter cambiare alphabet senza toccare il resto del codice (eg. se deciderai di aggiungere i numeri, non dovrai modificare l'if). Potresti anche utilizzare un dizionario per mappare le lettere dell'alfabeto con il rispettivo valore di chiave.
Come ulteriore consiglio ti dico: complica l'algoritmo e metti encryption e decryption dentro lo stesso programma. È poco utile perfezionare qualcosa di così corto e semplice, se inizi a fare qualcosa di un po' più intricato se ne riparla.
 
O ancora meglio:
Ruby:
if msg[char] >= 'a' and msg[char] <= 'z'
  # codice per cifrare
else
  encr_msg << msg[char]
end
Però i numeri, lettere maiuscole e altri rimangono sempre non crittati.

È poco utile perfezionare qualcosa di così corto e semplice, se inizi a fare qualcosa di un po' più intricato se ne riparla.
Io da quello che ho capito il progetto è fatto a scopi didattici, consiglierei di migliorare almeno il codice, è troppo semplice per essere pieno di bug.
 
Stato
Discussione chiusa ad ulteriori risposte.