2012-10-22 6 views
6

Mam problem z konwersją tekstu na ciąg Base64 w Javie (Android) i .NET (Visual Basic). Prosta (czytelna) forma znaków ASCII konwertuje dobrze. Ale jeśli chodzi o znaki specjalne (postacie, których kod jest większy niż 128), stwarzają dla mnie kłopoty.Java i .NET: błąd konwersji bazy64

Na przykład próbuję konwertować kod znaku, którego wartość ASCII to 65 (znak "A").

kod Mój Java jest:

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

I mojego kodu .NET jest:

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

te zwracają ten sam wynik: "QQ ==". Jest okej. Ale kiedy próbuję konwertować znak specjalny, na przykład kod znaku 153. Następnie zwraca różne wyniki.

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

ta zwraca "WPK ="

A moja sama kodu .NET:

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

zwraca ten "4oSi"

To jest takie dziwne. Co tu jest nie tak. Używam rodzimych bibliotek Base64 na obu platformach. Czy coś jest nie tak z moim kodem?

+6

Używasz UTF8 dla języka C#, a Java używa unikodu. Spróbuj użyć Unicode w obu. – Wug

+0

BTW - jak sądzisz, co reprezentuje postać 153? Nie można drukować w Unicode. Jest to znak towarowy (TM) w ISO-8859-1. –

+0

Próbowałem używać Unicode na obu, nadal istnieją różnice. .NET zwraca teraz "IiE =", podczas gdy Java nadal zwraca "wpk =". Tak 153 może być znakiem towarowym. Ale mój kod jest po prostu próbą wykonania szyfrowania przez szyfrowanie kodów znaków, więc różnią się one od 0-255. Następnie, aby bezpiecznie przesłać przez Internet, muszę przekonwertować go na Base64. –

Odpowiedz

9

Ponieważ dane, które kodujesz, są zaszyfrowanymi danymi - dane losowe, w których każdy bajt może mieć wartość od 0 do 255, a w stanie zaszyfrowanym nie ma znaczenia ani znaczenia tekstu, musisz traktować te informacje jako zawory it - true binary danych. Zarówno Java, jak i .NET mają pełną obsługę prawdziwych danych binarnych poprzez ich prymitywy z podstawowej tablicy bajtowej.

Jak wiadomo, kodowanie base64 to proces przekształcania prawdziwych danych binarnych (z zakresu od 0 do 255) w nieco większą tablicę danych binarnych (gdzie każdy bajt ma taką samą wartość, jak drukowany ASCII charakter gdzieś pomiędzy 32 a 126). Nazwijmy to encoded binary. encoded binary można następnie bezpiecznie przekonwertować na tekst, ponieważ praktycznie każdy znany zestaw znaków zgadza się z drukowalnym zestawem znaków ASCII (od 32 do 126).

więc głównym problemem z obu fragmentów Java i VB.NET jest to, że starają się wykorzystywać prymitywów tekstowych - char i ciąg w Javie; Łańcuch w VB.NET do przechowywania danych true binary. Kiedy to zrobisz, jest już za późno. Nie ma sposobu na niezawodną konwersję z powrotem na tablice bajtowe, ponieważ prymitywy tekstowe nie są po prostu zaprojektowane do bezpiecznego przechowywania i pobierania danych binarnych. Więcej informacji na temat dlaczego tak jest, proszę przeczytać The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

szczęście poprawka jest prosta. W przypadku języka Java nie należy używać znaków char i String do przechowywania danych binarnych. Umieść dane bezpośrednio w tablicy bajtów. Spróbuj wykonać następujące czynności:

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

uzyskać MQ ==

Rozwiązaniem jest koncepcyjnie takie same w VB.NET. Nie używaj String. Użyj tablicy bajtów.

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

Znowu - odpowiedź jest MQ ==

Wreszcie, po kodowaniu, to perfekcyjnie używać strun. Twoje znaki są w podzbiorze ASCII, a jakakolwiek konwersja między ciągiem a tablicą bajtową nie spowoduje uszkodzenia danych, ponieważ wszystkie zestawy znaków są zgodne w podzbiorze ASCII.

Pamiętaj, że będziesz mieć ten sam problem w odwrotnej kolejności - dekodowanie. Będziesz dekodować do tablicy bajtowej, po czym powrócisz do true binary. Od tego momentu dane nie mogą być przechowywane jako ciąg znaków - dopóki nie skończycie z nim - np. odszyfrowuje go z powrotem do oryginalnego czystego tekstu.

Mam nadzieję, że to pomoże.

+0

'System.Text.Encoding.UTF8.GetBytes (c)' zwraca tablicę bajtów w .NET. To, co piszesz o java, brzmi poprawnie. – faester

+0

@Guido Twój kod wydaje się działać. Nie jestem naprawdę dobry w Javie, więc domyślam się, że pomieszałem konwersję ciągu na bajt na base64. Próbuję osiągnąć to, że mam aplikację na Androida, która działa na danych XML. Więc wszystkie jego dane w postaci zwykłego tekstu. Następnie skonfigurowałem na nim serwer sieciowy z ASP.NET. Moja aplikacja na Androida służy do szyfrowania danych w pliku XML przy użyciu własnego kodu szyfrowania, dlatego też do gry wchodzą też takie znaki, jak 153. Następnie przekonwertuj go na Base64 i przesyłaj. Następnie na serwerze sieciowym opartym na .NET odbierze go i dekoduje z Base64 i odszyfrowuje go. –

+0

@FarazAzhar - dzięki za wyjaśnienia. Zaktualizowałem odpowiedź na podstawie lepszego zrozumienia problemu, który próbujesz rozwiązać. –