2016-02-05 79 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