2012-10-22 18 views
6

Non riesco a convertire il testo nella stringa Base64 in Java (Android) e .NET (Visual Basic). La semplice forma (leggibile) di caratteri ASCII converte bene. Ma quando si tratta di personaggi speciali (personaggi il cui codice è maggiore di 128), stanno creando problemi per me.Java e .NET: confusione di conversione Base64

Ad esempio, provo a convertire un codice di carattere il cui valore ASCII è 65 (il carattere "A").

codice Java è mio:

char a = 65; 
String c = String.valueOf(a); 
byte bt[] = c.getBytes();    
String result = Base64.encodeToString(bt, Base64.DEFAULT); 

E il mio codice .NET è:

Dim c As String = Chr(65) 
Dim result as String = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(c)) 

Questi entrambi restituire lo stesso risultato: "QQ ==". Questo va bene. Ma quando provo a convertire un carattere speciale, ad esempio un codice di carattere 153, restituisce risultati diversi.

char a = 153; 
String c = String.valueOf(a);    
byte bt[] = c.getBytes();    
String result = Base64.encodeToString(bt, Base64.DEFAULT); 

Ciò restituisce "PLC ="

E il mio stesso codice .NET:

Dim c As String = Chr(153) 
Dim result as String = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(c)) 

Ciò restituisce "4oSi"

Questo è così strano. Cosa c'è di sbagliato qui. Sto usando le librerie native Base64 su entrambe le piattaforme. C'è qualcosa che non va nel mio codice?

+6

Si sta utilizzando UTF8 per C# e Java utilizza Unicode. Prova ad usare l'unicode in entrambi. – Wug

+0

BTW - cosa pensi che rappresenti il ​​personaggio 153? Non è stampabile in Unicode. È un marchio (TM) in ISO-8859-1. –

+0

Ho provato ad usare Unicode su entrambi, ancora ci sono differenze. .NET ora restituisce "IiE =" mentre Java restituisce ancora "wpk =". Sì 153 potrebbe essere il segno del marchio. Ma il mio codice sta semplicemente cercando di eseguire una crittografia rimescolando codici carattere in modo da variare tra 0-255. Quindi per trasmettere in modo sicuro su Internet ho bisogno di convertirlo in Base64. –

risposta

9

Dato che i dati che si codifica sono dati crittografati - dati casuali in cui qualsiasi byte può essere compreso tra 0 e 255 e, nel suo stato crittografato, non ha alcun significato di carattere o testo, è necessario trattare queste informazioni come chiamate -let it - true binary dati. Sia Java che .NET hanno pieno supporto per i veri dati binari tramite i rispettivi primitivi dell'array di byte.

Come sapete, la codifica base64 è il processo di conversione di dati binari veri (con un intervallo da 0 a 255) in una matrice leggermente più grande di dati binari (in cui ogni byte è garantito per avere lo stesso valore di un ASCII stampabile personaggio da qualche parte tra 32 e 126). Chiamiamo questo encoded binary. encoded binary può quindi essere convertito in testo in modo sicuro perché praticamente tutti i set di caratteri noti sono compatibili con il set di caratteri ASCII stampabile (da 32 a 126).

Quindi il problema principale con entrambi i snippet Java e VB.NET è che si sta tentando di utilizzare le primitive di testo - char e String in Java; Stringa in VB.NET per memorizzare i dati true binary. Una volta che lo fai, è troppo tardi. Non è possibile convertirlo in modo affidabile in array di byte perché le primitive di testo non sono semplicemente progettate per archiviare e recuperare in modo sicuro i dati binari. Per ulteriori informazioni sul perché è così, leggere The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

Fortunatamente la soluzione è semplice. Per Java, non utilizzare char e String per memorizzare dati binari. Metti i dati direttamente in un array di byte. Provare quanto segue:

byte [] bt = new byte[1]; 
    bt[0] = (byte) 153; 
    String result = Base64.encodeToString(bt, Base64.DEFAULT); 

ottengo mQ ==

La correzione è concettualmente lo stesso in VB.NET. Non usare String. Usa un array di byte.

Dim bytes() As Byte = New Byte() {153} 
    Dim result As String = Convert.ToBase64String(bytes) 

nuovo - la risposta è MQ ==

Infine, dopo la codifica, è perfettamente bene usare Corde. I tuoi caratteri sono nel sottoinsieme ASCII e qualsiasi conversione tra String e l'array di byte non danneggerà i dati perché tutti i set di caratteri sono d'accordo sul sottoinsieme ASCII.

Ricordare che si verificherà lo stesso problema nell'ordine inverso: decodifica. Si decodificherà su un array di byte, a quel punto si tornerà a true binary. Da questo punto in poi i dati non devono mai essere memorizzati come una stringa - finché non hai finito con esso - ex. decodificandolo nuovamente al testo originale.

Spero che questo aiuti.

+0

'System.Text.Encoding.UTF8.GetBytes (c)' restituisce un array di byte in .NET. Quello che scrivi sui suoni java è corretto. – faester

+0

@Guido il tuo codice sembra funzionare. Non sono molto bravo con Java quindi suppongo di aver incasinato la conversione da stringa a byte a base64. Quello che sto cercando di realizzare è che ho un'app per Android che funziona su dati XML. Quindi sono tutti dati in chiaro. Quindi ho creato un server web con ASP.NET su di esso. La mia app per Android è quella di crittografare i dati del file XML utilizzando il mio codice di crittografia, ecco perché anche i personaggi come 153 entrano in gioco. Quindi convertirlo in Base64 e trasmetterlo. Quindi sul server web basato su .NET lo riceverà e decodificherà da Base64 e decrittalo. –

+0

@FarazAzhar - grazie per il chiarimento. Ho aggiornato la risposta in base a una migliore comprensione del problema che stai cercando di risolvere. –