2016-02-05 89 views
2

我試圖重新從VB.NET PasswordDeriveBytes的實施,到目前爲止,我在iOS的Objective C的代碼已經實現了讓我從一個Java實現不同的結果。SHA1消息摘要和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); 
    } 
} 

雖然下面是構造函數的目標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; 
} 

由於據我研究,對Java的hash.digest(input)實行的是相同的OBJ-C [hash updateWith:firstToLastDigest length:(CC_LONG)strlen(firstToLastDigest)]; outputBuffer = [hash final];,但我得到不同的結果。

在這一點上我沒有別的想法,爲什麼他們得到不同的值,所以任何指導或建議,歡迎。

回答

1

後剝開我的頭髮,4天回答我的問題。

似乎CommonCrypto的CC_SHA1_Final()不會重置CC_SHA1_CTX對象上下文,儘管蘋果文檔聲明它會這樣做,這會導致輸出的差異。

從蘋果文檔:https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/CC_SHA1_Final.3cc.html

CC_SHA1_Final()放在MD的消息摘要,其中必須有空間CC_SHA1_DIGEST_LENGTH == 20個 輸出的字節,並擦除CC_SHA1_CTX。

我不得不編輯NV-IOS-消化庫和手動重置每個- (unsigned char *)final方法CC_SHA1_CTX對象顯示如下:

- (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