Reputation: 55
We are trying to duplicate the sha1 crypto encoding done in our java 1.6 server with the iOS/iPhone CommonCrypto libraries.
A basic question I have is why does Java have a fix output of 40 bytes while iOS has a fix output of 20 bytes from the SHA1 algorithms
I have found this link which shows how to generate the encoding in both environments but the output would be of different lengths, correct?
How to SHA1 hash a string in Android?
Upvotes: 1
Views: 1996
Reputation: 2737
Android or iOS, the SHA-1 has an expected length of 20 bytes.
But there is a difference in the sha-1 algorithm return.
iOS simply does not terminate the result with a null character.
So I guess the point is to not use the sha output length to generate the output data, but the CC_SHA1_DIGEST_LENGTH constant - which is 20.
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
NSData* data = [stringToHash dataUsingEncoding:NSUTF8StringEncoding];
char* sha = CC_SHA1(data.bytes, data.length, digest);
NSData *hashedData = [NSData dataWithBytes:sha length:CC_SHA1_DIGEST_LENGTH];
If you terminate the digest yourself, then the sha output is correct:
uint8_t digest[CC_SHA1_DIGEST_LENGTH+1];
memset(digest,0,CC_SHA1_DIGEST_LENGTH+1);
NSData* data = [stringToHash dataUsingEncoding:NSUTF8StringEncoding];
char* sha = CC_SHA1(data.bytes, data.length, digest);
NSData *hashedData = [NSData dataWithBytes:sha length:strlen(sha)];
Hope it helps, cheers :)
Upvotes: 0
Reputation: 143
Yesterday i was facing exactly this problem, the sha1 algorithm implementation i was using, was not compatible with the android one, after more or less one hour searching on android and ios implementations, i realize it was only a problem of String Formating. (change X to x).
Im sharing the snippet of what we are using for sha1 algorithm implementation ios/android compatible ... Hope this helps as a version of @poupou theory answer :-).
public static String sha1(String s) {
MessageDigest digest = null;
try {
digest = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
digest.reset();
byte[] data = digest.digest(s.getBytes());
return String.format("%0" + (data.length * 2) + "X", new BigInteger(1, data));
}
-(NSString*) sha1:(NSString*)input
{
const char *cstr = [input cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:input.length];
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, data.length, digest);
NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++)
[output appendFormat:@"%02X", digest[i]];
return output;
}
Upvotes: 0
Reputation: 43553
The SHA1 algorithm always return 160 bits (or 20 bytes).
I suspect your Java code is turning the byte array into a hexadecimal string, i.e. where each byte would show as two characters.
To compare this with CommonCrypto you can either:
convert the Java output to a byte array; or
convert the CommonCrypto byte array to an hexadecimal string (this is what the link in your question is doing)
before comparing the values.
Upvotes: 2