Visualizzazione dei risultati da 1 a 8 su 8

Discussione: Secure Hash Algoritm

  1. #1

    Secure Hash Algoritm

    Buongiorno,

    avrei bisogno di un consiglio per implementare l'algoritmo SHA1 in Java.

    Prendo come esempio la String "ciao"

    Il primo step è questo:

    decodififare una String in bit (o byte)

    Da "ciao" ottengo

    "c" = 99 = 01100011
    "i" = 105 = 01101001
    "a"= 97 = 01100001
    "o" = 111 = 01111001

    Questa è la rappresentazione decimale e binaria dei caratteri della String "ciao".

    Dovrei ora, a partire dal carattere "c" fino al carattere "o", dovrei "affiancare" le sequenze di bit ottenute.

    Dunque ottenere questo:

    01100011 01101001 01100001 01111001

    Cioè. per quanto riguarda la parola "ciao", una sequenza di 32 bit.

    A questo punto, devo

    a) inserire un bit 1 a destra della sequenza per ottenere:

    01100011 01101001 01100001 01111001 1

    Come posso riuscirci?

    Nel senso: inserire un bit = 1 a destra di una sequenza di bit corrisponde ad effettuare uno shift a destra di una posizione e aggiungere 1.

    Di seguito però dovrei aggiungere alla sequenza ottenuta un numero di bit = 0 tali che il numero totale di bit della sequenza ottenuta risulti uguale a

    448 mod 512...

    Se ho capito a livello pratico a cosa corrispondono queste operazioni, non so con che tipo di dati operare:

    un int in java corrisponde a 32 bit, un long, se non ricordo male, a 64 bit.

    Io qui devo lavorare con blocchi lunghi 512 bit... o 164 byte fate vobis.

    Come mi conviene operare per dati come questi?

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: Secure Hash Algoritm

    Originariamente inviato da ragnonerodocet
    A questo punto, devo

    a) inserire un bit 1 a destra della sequenza per ottenere:

    01100011 01101001 01100001 01111001 1

    Come posso riuscirci?
    Innanzitutto una cosa, e preciso non è assolutamente per criticare. Il SHA-1 (160 bit) non è proprio una stupidata da implementare.... nel senso che non questione solo di "uno shift" ma anche molto ben altro.
    E invece ... sei ancora con la questione di come fare uno shift?? Uno shift su un tipo di dato intero in Java si fa con gli operatori << e >> e >>> (come anche in altri linguaggi).
    La questione appunto non è tanto lo shift ... ma come gestire tutto l'algoritmo che banale non è. Ed è chiaro che non puoi trattare 512 bit per intero, visto che in Java il tipo di dato intero più grande è il long a 64 bit. Il nocciolo di tutto sta nel usare più "parole" di 32 o 64 bit (in generale quello che è disponibile per un linguaggio/piattaforma) per comporre tutta la elaborazione.

    Io personalmente non ho mai implementato da zero SHA-1 o affini, quindi non ti so dire esattamente cosa fare. Posso dirti che è meglio se ti documenti bene. C'è la pagina di Wikipedia http://en.wikipedia.org/wiki/SHA-1 che mi pare abbastanza completa.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Ho letto la documentazione che mi ha fornito, fortunatamente avevo già materiale che mi dava una bella mano.

    Ho terminato l'implementazione dell'algoritmo, ma semplicemente il risultato non è quello giusto.

    Il passaggio carine si ha a mio avviso nel momento in cui opero sull'array di byte ottenuto in questa maniera

    codice:
    byte[] b = new String("a").getBytes("utf-8");
    L'algoritmo SHA1 prevede innanzitutto di processare una sequenza di bit.

    Nel mio caso, essendo la lunghezza del base block da processare di 512 bit, uso un array di 64 Byte.

    I pirmi elementi di tale array vanno valorizzati con i byte corrispondenti alla stringa da processare. A tale sequenza di bit così ottenuti va aggiunto un 1 a destra.

    Io ho pensato di ottenere questo così (prendo in esame la stringa "a")



    codice:
    byte[] to_convert = new String ("a").getBytes("utf-8");
    
    byte[] theByteArray = new byte [NUM_BYTE];  //array di 64 elementi
    
    /*inizializzo il primo elemento di theByteArray con l'unico elemento di to_convert*/
    theByteArray[0]=to_convert[0];
    In questo modo, nel primo byte di theByteArray è presente il byte 97. A questo faccio seguire, come secondo elemento di theByteArray, il byte MIN_BYTE_NUM = -128

    codice:
    theByteArray[1]=MIN_BYTE_NUM;
    Volevo chiedere dopo questa dissertazione noiosa:

    riesco, con questo esempio, a ottenere che il primo elemento dell'array sia

    01100001 //97 in binario

    e che il secondo sia

    10000000 //-128 in binario???

    Questo perchè, se la risposta è si, altri passaggi sono sbagliati!

    Naturalmente, sono ben accette tutte le possibili osservazioni di chiunque per migliorare!

    Grazie dell'attenzione, buona giornata a tutti.

  4. #4
    Aggiorno il problema!!!

    L'algoritmo di SHA1 è riuscito!!!

    Solo un piccolo problema... Funziona solo se la stringa da decodificare è la stringa vuota...

    Quindi ho la certezza che

    - se passo all'algoritmo la giusta sequenza di bit allora i calcoli sono giusti!!!

    Quindi io faccio la cosa più semplice: cerco di trovare l'SHA1 della stringa "a".

    In genere, l'algoritmo lavora su sequenze di bit. Dunque devo decodificare la Stringa "a" in una serie di bit

    Io faccio direttamente questo

    codice:
    byte[] bt = new String ("a").getBytes;
    Da quello che vedo, nell'array di byte da processare, il primo byte è uguale a 97, il secondo a -128

    Dunque è come se scrivessi:

    01100001 - 10000000

    Ma se il risultato è sbagliato vuol dire che qualcosa non va...

    L'unica cosa che mi viene da pensare è che un char sono 4 byte... Dunque forse dovrei passare, sempre se scrivessi "a":

    00000000 - 00000000 - 00000000 - 01100001

    Cioè 97 su 4 byte...

    Secondo voi?

  5. #5
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,328
    Originariamente inviato da ragnonerodocet
    L'unica cosa che mi viene da pensare è che un char sono 4 byte... Dunque forse dovrei passare, sempre se scrivessi "a":

    00000000 - 00000000 - 00000000 - 01100001

    Cioè 97 su 4 byte...

    Secondo voi?
    Dipende tutto da come ottieni i byte: la parte di codice che hai postato non è completa/corretta quindi tutto può essere.

    Se usi getBytes() della classe String hai tre possibilità (una è deprecata):

    • getBytes()
    • getBytes(String charset)
    • getBytes(Charset charset)


    La prima forma restituisce i byte della stringa usando il Charset di default della piattaforma dove stai eseguendo. Quindi, anche in questo caso, tutto può essere.

    La seconda e la terza, impongono un Charset. Prendendo la seconda (più veloce), puoi indicare il charset da utilizzare in questo modo:

    codice:
    byte[] myBytes = tuaStringa.getBytes("UTF-8");
    
    oppure
    
    byte[] myBytes = tuaStringa.getBytes("UTF-16");
    Supponendo che la tua stringa sia composta da un solo carattere ( "a" ), con la prima otterrai un solo byte, con la seconda ne otterrai 4:

    codice:
    // Con la prima:
    myBytes.length --> 1
    myBytes[0] = 97
    
    // Con la seconda
    myBytes.length --> 4
    myBytes[0] = -2
    myBytes[1] = -1
    myBytes[2] = 0
    myBytes[3] = 97
    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da ragnonerodocet
    L'algoritmo di SHA1 è riuscito!!!

    Funziona solo se la stringa da decodificare è la stringa vuota...
    Scusa ma mi pare un po' un controsenso che dici che l'algoritmo è "riuscito" e poi precisi solo con stringa vuota.

    A questo punto magari posta il codice del tuo algoritmo, così si può vedere se almeno rispecchia (anche solo a grandi linee) quanto detto in quella pagina di wikipedia che ho linkato.

    Poi comunque mi pare di capire che sei ancora ai dubbi di quanti byte gestire e come trattarli ecc.... quindi penso un po' lontano dalla soluzione finale (e ripeto, non è per criticare o supporre chissà che cosa).

    E se vuoi verificare se un tuo risultato è corretto, ci sono tools online per calcolare il SHA1 e puoi anche farlo con il java.security.MessageDigest del framework.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  7. #7
    In realtà, svelato l'arcano!!!

    Perchè riusciva con Stringa vuota e non con altre String?

    Semplice... Perchè la stringa vuota ha length 0!!!

    L'algoritmo SHA1 prevede questo:

    prendo, con codifica a 8 bit, i bytes corrispondenti alla Stringa inserita:

    Dunque mettiamo l'esempio di String stringa_mia = "ab";

    Il getBytes invocato con argomneto stringa_mia corrisponde a fare questo

    byteArray[0] = 97;
    byteArray[1] = 98;

    Deve poi essere inserito un 1 alla fine dei bit corrispondenti

    01100001 - 01100010 - 1

    Cioè il byte b = -128

    Il punto stava nel fatto che, negli ultimi 16 bit (2 byte) dei 512 presi in esame

    NON VA MESSA LA LUNGHEZZA DELL'ARRAY OTTENUTO MA IL NUMERO DI BYTE DA PROCESSARE...

    cioè la lunghezza della stringa (o dell'array di byte) moltiplicato per 8....

    Stringa vuota ha lunghezza 0, e sappiamo tutti che moltiplicando 0 per 8 otteniamo sempre 0....

    Era più semplice del previsto... Ma nel marasma generale non ho mai alla soluzione....

    Grazie a tutti.

  8. #8
    Continuo su questa discussione per non aprirne altre.

    Alla fine dell'algoritmo, ottengo un numero intero come questo:

    216493578

    che tradotto in binario (su 32 bit, essendo un int) corrisponde a

    00001100 | 11100111 | 01101110 | 00001010

    Come si vede, le prime 4 cifre sono zeri.

    Quando vado a convertire l'intero in esadecimale ottengo:

    ce76e0a

    Sono 7 cifre esadecimali: manca la prima, perchè nell'operare su un intero (216493578), nella conversione perde la prima cifra significativa dell'esadecimale (che è 0 esadecimale ==> 0000 in binario)

    Se teoricamente il numero risultante fosse 0 invece che 216493578, otterrei una sola cifra esadecimale.

    Come posso ottenere la stampa forzata di 8 elementi, considerando anche gli eventuali 0 iniziali?

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.