2016-02-05 6 views
2

Я пытаюсь воссоздать реализацию PasswordDeriveBytes из VB.NET, и до сих пор я реализовал в iOS Objective C код, дающий мне разные результаты из реализации Java.SHA1 Обновления MessageDigest и CommonCrypto, получающие разные результаты

Причина, по которой мы пытаемся воссоздать реализацию PasswordDeriveBytes, заключается в том, что клиентская сторона использует ее для шифрования/дешифрования данных и из того, что я искал, PasswordDeriveBytes использует PBKDF1, который устарел. Реализация Java возвращает ожидаемое зашифрованное значение и успешно расшифровывается сервером. Однако значение, возвращаемое из реализации iOS ObjC, неверно.

Ниже реализация Java из Конструктора, взятый из этого ответа: Encryption Diff Between Java and C#

public static class PasswordDeriveBytes{ 

private final MessageDigest hash; 

private final byte[] firstToLastDigest; 
private final byte[] outputBuffer; 

private int position = 0; 

public PasswordDeriveBytes(String password, byte[] salt, int iterations) { 
    try { 
     this.hash = MessageDigest.getInstance("SHA-1"); 

     this.hash.update(password.getBytes("UTF-8")); 
     this.hash.update(salt); 
     this.firstToLastDigest = this.hash.digest(); 
     // At this point, the Obj-C and Java values are the same 
     // this.firstToLastDigest = b8fa3d36.... 

     for (int i = 1; i < iterations - 1; i++) { 
      System.out.println(" Iterate " + i); 
      hash.update(firstToLastDigest); 
      hash.digest(firstToLastDigest, 0, firstToLastDigest.length); 
     } 

     this.outputBuffer = hash.digest(firstToLastDigest); 
     // However at this point, they become different 
     // Java has outputBuffer = f498e100... 
     // Obj-C has outputBuffer = <d7d5fa71... 

    } catch (UnsupportedEncodingException|NoSuchAlgorithmException | DigestException e) { 
     throw new IllegalStateException("SHA-1 digest should always be available", e); 
    } 
} 

Хотя ниже является Objective C код конструктора, с помощью этой библиотеки: https://github.com/TakahikoKawasaki/nv-ios-digest

@implementation PasswordDeriveBytesObjC 
{ 
    SHA1 *hash; 
    Byte *firstToLastDigest; 
    Byte *outputBuffer; 

    int position; 
} 

- (instancetype)initWithPassword:(NSString *)password salt:(NSData *)salt iterations:(int)iterations 
{ 
    self = [[[self class] alloc] init]; 
    if (self){ 
     hash = [[SHA1 alloc] init]; 

     const char* ASCIIpassword = [password cStringUsingEncoding:NSUTF8StringEncoding]; 
     NSData *passwordData = [NSData dataWithBytes:ASCIIpassword length:strlen(ASCIIpassword)]; 

     [hash updateWith:[passwordData bytes] length:(CC_LONG)[passwordData length]]; 
     [hash updateWith:[salt bytes] length:(CC_LONG)[salt length]]; 
     firstToLastDigest = [hash final]; 
     // At this point, the Obj-C and Java values are the same 
     // firstToLastDigest = <b8fa3d36.... 

     for (int i = 1; i < iterations - 1; i++){ 
      [hash updateWith:firstToLastDigest length:(CC_LONG)strlen(firstToLastDigest)]; 
     } 

     [hash updateWith:firstToLastDigest length:(CC_LONG)strlen(firstToLastDigest)]; 
     outputBuffer = [hash final]; 
     // However at this point, they become different 
     // Java has outputBuffer = f498e100... 
     // Obj-C has outputBuffer = <d7d5fa71... 

    } 
    return self; 
} 

As насколько я исследовал, реализация hash.digest(input) java такая же, как [hash updateWith:firstToLastDigest length:(CC_LONG)strlen(firstToLastDigest)]; outputBuffer = [hash final]; в Obj-C, но у меня разные результаты.

На данный момент у меня нет других идей относительно того, почему они получают разные значения, поэтому любые рекомендации или предложения приветствуются.

ответ

1

Отвечая на мой собственный вопрос после 4-х дней разрывания моих волос.

Похоже, что CC_SHA1_Final() CryptCrypto не сбрасывает контекст объекта CC_SHA1_CTX, несмотря на то, что документация на Apple указывает, что это так, что вызывает несоответствия в выходе.

От компании Apple Docs: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/CC_SHA1_Final.3cc.html

CC_SHA1_Final() помещает сообщение переваривать в мкр, который должен иметь место для CC_SHA1_DIGEST_LENGTH == 20 байт вывода, и стирает CC_SHA1_CTX.

мне пришлось редактировать NV-КСН-дайджест библиотеки и вручную сбросить CC_SHA1_CTX объект в каждом - (unsigned char *)final способа, как показано ниже:

- (unsigned char *)final 
{ 
    CC_SHA1_Final(_digest, &_context); // <-- _context does not reset 
    CC_SHA1_Init(&_context); // <-- manually reset the CC_SHA1_CTX object 

    _description = [NSString stringWithFormat: 
        @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 
        _digest[ 0], _digest[ 1], _digest[ 2], _digest[ 3], 
        _digest[ 4], _digest[ 5], _digest[ 6], _digest[ 7], 
        _digest[ 8], _digest[ 9], _digest[10], _digest[11], 
        _digest[12], _digest[13], _digest[14], _digest[15], 
        _digest[16], _digest[17], _digest[18], _digest[19]]; 

    return _digest; 
} 

Надеется, что это помогает кому-то. :)

+1

спасибо, что указал мне в правильном направлении! – Jakob