2009-10-28 12 views
16

I zostały łzawienie włosy przez cały dzień próbuje rozwiązać ten ...różnica między iPhone AES (objective-c) i Java

Mam klienta, Objective-C działa na iPhone, podłączenie do Jawy serwer. IPhone szyfruje dane za pomocą AES, ale nie mogę odszyfrować go na serwerze. Używam znanego hasła i komunikatu (pojedynczy ciąg) i generuję tablicę bajtów w telefonie iPhone, generując tablicę bajtów porównania na serwerze Java za pomocą tego samego klucza i komunikatu, ale tablice bajtów są zupełnie inne (i dlatego nie mogą być dekodowane po stronie Java).

Klient korzysta z biblioteki CommonCrypto z następującymi ustawieniami ...

danych jest NSData przytrzymanie „komunikat” słowo używając dataUsingEncoding:NSASCIIStringEncoding Klucz jest NSData trzymając frazę „1234567891123456” ponownie stosując kodowanie jako powyżej. algorytm kCCAlgorithmAES128 Opcje jest kCCOptionsPKCS7Padding (co wierzę przyrównuje do EBC na serwerze ?!)

Serwer jest za pomocą następującego kodu ...

byte[] key = "1234567891123456".getBytes(); 
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding"); 

SecretKeySpec k = new SecretKeySpec(key, "AES"); 
c.init(Cipher.ENCRYPT_MODE, k); 
byte[] encryptedData = c.doFinal("message".getBytes()); 

ale dane w encryptedData nie pasuje to, co jest generowane w kodzie celu-c, tablice bajtów są zupełnie inne.

Czy ktoś może zobaczyć cokolwiek oczywistego, że robię źle? myślę ustawienia są takie same ... :(

  • UPDATE - Zgodnie z życzeniem ....

Ok, więc tutaj jedzie ....

iPhone klient szyfrowanie następującego ciągu "wiadomość" Używa klucza "1234567891123456" Używa wektora inicjalizacyjnego "1010101010101010" Używa AES128, z trybem CBC (o ile wiem) i opcjami kCCOptionsPKCS7Padding

Wynik szyfrowania (z kodowaniem base64) jest UHIYllDFAXl81ZM7OZPAuA ==

Serwer jest zaszyfrowanie ten sam ciąg, z tym samym kluczem i wektorem inicjalizacji. Używa następującej Cipher.getInstance ("AES/CBC/PKCS5Padding");

Wynikiem kodowania (kodowanie base64) jest ALBnFIHysLbvAxjvtNo9vQ ==

Dzięki.

  • UPDATE 2 - Zgodnie z życzeniem ...

Oto kod iPhone ....

NSData *toencrypt = [@"message" dataUsingEncoding:NSASCIIStringEncoding]; 

NSData *pass = [@"1234567891123456" dataUsingEncoding:NSASCIIStringEncoding]; 

NSData *iv = [@"1010101010101010" dataUsingEncoding:NSASCIIStringEncoding];  

CCCryptorStatus status = kCCSuccess; 

NSData *encrypted = [toencrypt dataEncryptedUsingAlgorithm:kCCAlgorithmAES128 key:pass initializationVector:iv options:kCCOptionPKCS7Padding error:&status]; 

NSString *text = [NSString base64StringFromData:encrypted length:[encrypted length]]; 

kategoria NSData do szyfrowania pochodzi stąd ...

http://github.com/AlanQuatermain/aqtoolkit/tree/master/CommonCrypto/

Nawiasem mówiąc, mam zaznaczone tablice bajtów, które są w toencrypt, pass i iv i dopasować te, które znajdują się na serwerze.

+0

Zmieniono serwer, aby korzystać z EBC zgodnie z sugestią i nadal nie działa. Nawiasem mówiąc zauważyłem serwer używający PKCS5 i klienta używającego PKCS7, ale nie ma 5 dostępnych na kliencie i 7 dostępnych na serwerze, i podobno są one kompatybilne. –

+0

Tak, wypełnienie PKCS7 jest takie samo jak PKCS5Padding. Jeśli zmiana na ECB nie zadziałała, prawdopodobnie iPhone używa trybu CBC. Musisz określić wektor inicjujący i upewnić się, że serwer używa tego samego. – erickson

+0

Dzięki za odpowiedzi. Stworzyłem IV sam na kliencie i na serwerze, ale nadal nie działa. To tutaj brakuje solidnej i niezawodnej biblioteki AES dla iPhone'a! :( –

Odpowiedz

3

To nie jest moja dziedzina, ale wygląda na to, że masz klienta PKCS7, ale na serwerze masz PKCS5.

+0

Od [wikipedia] (http://en.wikipedia.org/wiki/Padding_%28cryptography%29) tryby są wymienne. – lupz

2

Jakiego trybu używa iPhone z AES? Nie wymieniasz niczego, więc może to oznacza, że ​​nie używasz łańcucha (ECB).

Jednak po stronie Java używasz CBC, ale nie określasz wektora inicjalizacyjnego. To zdecydowanie jest złe. Jeśli naprawdę używasz CBC, masz mieć, aby mieć IV, który był używany podczas szyfrowania. IV nie jest tajemnicą; może zostać wysłany wraz z zaszyfrowanym tekstem.

Jeśli naprawdę używasz ECB, nie ma IV, ale Twoja Java określa niewłaściwy tryb.

0

Na podstawie próbek serwer robi to dobrze, a klient nie.

Patrząc na dane, zgaduję, że klucz jest nieprawidłowy. Pokaż nam kod telefonu iPhone, szczególnie kod do "1234567891123456" na klucz.

+0

Dodano do pierwotnego postu zgodnie z żądaniem. –

0

Niedawno natknąłem się na to w innym projekcie. Problem polegał na tym, że klucz był zbyt długi o jeden bajt, aby zmieścić się w buforze char wewnątrz metody dataEncryptedUsingAlgorithm.

Problem polegał na tym, że metoda getBytes na urządzeniu NSString była słabo awaryjna. Skopiowałoby to większość ciągu znaków do bufora, ale ponieważ klucz był zbyt długi o jeden bajt, oznaczałoby to operację jako nieudaną, ustawiając pierwszy znak na NUL (znak 0).

Wejdź do tej metody w Xcode i zobacz jak wygląda twój bufor znaków [16]. Może mieć ten sam problem i mieć zawartość { 0, '2', '3', '4', ... }.

3

Właśnie przebiegłem dokładnie ten sam problem. Używam CommonCrypto na kliencie z systemem iOS, używając ustawienia:

NSData * encrypted = [data dataEncryptedUsingAlgorithm:kCCAlgorithmAES128 key:pass initializationVector:iv options:kCCOptionPKCS7Padding error:&status]; 

Serwer używa Cipher.getInstance("AES/CBC/PKCS5Padding"); z tego samego klucza i wektora inicjalizacji co klient.

Po walić głową w ścianę w ciągu ostatnich kilku godzin, ale w końcu po porady Jasona i sprawdzone procedury dataEncryptedUsingAlgorithm i wydrukowane keyData zaraz po FixKeyLengths. Okazuje się, że mój 128-bitowy klucz został rozszerzony do 192 bitów z dodanymi 0 do końca. Po naprawieniu tego wszystko działa poprawnie. :)

Aktualizacja: Moja odpowiedź została wysłana prawie 2 lata temu, a ten problem wydaje się być rozwiązany w najnowszym kodzie NSData+CommonCrypto. W szczególności, jest to część, która spowodowała problem:

static void FixKeyLengths(CCAlgorithm algorithm, NSMutableData * keyData, NSMutableData * ivData) 
{ 
    NSUInteger keyLength = [keyData length]; 
    switch (algorithm) 
    { 
    case kCCAlgorithmAES128: 
    { 
     if (keyLength <= 16) 
     { 
     [keyData setLength: 16]; 
     } 
     else if (keyLength <= 24) 
     { 
     [keyData setLength: 24]; 
     } 
     else 
     { 
     [keyData setLength: 32]; 
     } 

     break; 
    } 

Pierwsza kontrola keyLength <= 16 nie był tam wcześniej.

Jeśli nadal występują problemy, to prawdopodobnie coś innego.

+0

Witam mam ten sam problem, możesz podzielić się przykładowym kodem. Dziękuję Ci. –

+0

@ylian: Mam do czynienia z tym samym problemem. Udostępnij swój kod. –

Powiązane problemy