I'm trying to recreate the implementation of PasswordDeriveBytes from VB.NET and so far I have implemented in iOS Objective C code its giving me different results from a Java implementation.
The reason why we try to recreate the implementation of PasswordDeriveBytes is because the client server side is using it to encrypt/decrypt data and from what I've searched, PasswordDeriveBytes uses PBKDF1, which is outdated. The Java implementation is returning the expected encrypted value and is being decrypted by the server successfully. However the value returned from the iOS ObjC implementation is incorrect.
Below is the Java implementation of the Constructor, taken from this answer: 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);
}
}
While below is the Objective C Code of the constructor, using this library: 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 far as I have researched, the implementation of hash.digest(input)
of java is the same as [hash updateWith:firstToLastDigest length:(CC_LONG)strlen(firstToLastDigest)]; outputBuffer = [hash final];
in Obj-C but I am getting different results.
At this point I have no other ideas as to why they get different values, so any kind of guidance or suggestions are welcome.