Finding and Hashing IDs

When you are performing Server-to-Server in-app integration, you will need to locate some IDs yourself. Below are some quick tips on how to find and hash IDs.

Our network requires that you use hashing to encode IDs. There are two accepted forms of hashing: Secure Hashing Algorithm (SHA-1) and Message Digest Algorithm (MD5).

When hashing data, the raw value should be properly formatted so that your resulting hash is identical to ours. Matching on hashed IDs requires that they be identical (i.e., case-sensitive and using the correct ID.)

For example, the IDs AbcD123 and ABCD123 are not identical. Please make sure that the ID is correct before hashing it.

Android

Hashing Android IDs to Create the MMDID

We track requests on Android devices by using the Android ID.

The following code, when implemented, will obtain and hash the Android ID in the required format using the MD5 and SHA-1 and appending the “mmh_” to generate a string with the required format of mmh_[MD5]_[SHA1].

...
mmdid = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID);

if(mmdid == null)
return null;

mmdidBuilder = new StringBuilder("mmh_");
try
{
md = MessageDigest.getInstance("MD5");
hashBytes = md.digest(mmdid.getBytes());
mmdidBuilder.append(byteArrayToString(hashBytes));

mmdidBuilder.append("_");
md = MessageDigest.getInstance("SHA1");
hashBytes = md.digest(mmdid.getBytes());
mmdidBuilder.append(byteArrayToString(hashBytes));
}
catch(Exception e)
{
MMSDK.Log.v(e.getMessage());
return null;
}
return mmdidBuilder.toString();
...

iOS

Apple devices such as iPhone, iPad or iPod Touch are assigned Identifiers for Advertisers (IFDAs) starting with iOS version 6. We require the hashed IDFA (HAID) and the WiFi MAC address on each call.

Hashing the IDFA to Create the HAID - Used for iOS Versions 6 and above

The following code, when implemented, will obtain and hash the IDFA in the required format using the MD5 and SHA-1 and appending the “mmh_” to generate a string with the required format of mmh_[MD5]_[SHA1].

Importing the HAID

Only one import will be needed for the HAID.

...
#import <CommonCrypto/CommonDigest.h>
...

The following iOS code, when implemented, will return a hashed version of the IDFA value for the device in the required format.

The required format is “mmh_[MD5]_[SHA1]”

...
+ (NSString *)haid:(BOOL)hash {
#ifndef PRE_6    
    Class asIDManagerClass = NSClassFromString(@"ASIdentifierManager");
    if (asIDManagerClass) {
        NSString *adId = nil;
        
        SEL sharedManagerSel = NSSelectorFromString(@"sharedManager");
        if ([asIDManagerClass respondsToSelector:sharedManagerSel]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
            id adManager = [asIDManagerClass performSelector:sharedManagerSel];
            if (adManager) {
                SEL advertisingIdentifierSelector = NSSelectorFromString(@"advertisingIdentifier");
                
                if ([adManager respondsToSelector:advertisingIdentifierSelector]) {
                    
                    id uuid = [adManager performSelector:advertisingIdentifierSelector];
                    
                    if (!uuid) {
                        return nil;
                    }
                    
                    SEL uuidStringSelector = NSSelectorFromString(@"UUIDString");
                    if ([uuid respondsToSelector:uuidStringSelector]) {
                        adId = [uuid performSelector:uuidStringSelector];
#pragma clang diagnostic pop
                    }
                }
            }
        }
        
        if (!adId) {
            return nil;
        }
        
        if (hash) {
            //MD5
            const char *cStr = [adId UTF8String];
            unsigned char result[16];
            CC_MD5(cStr, strlen(cStr), result);
            NSString *md5 = [NSString stringWithFormat: @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
                             result[0], result[1], result[2], result[3],
                             result[4], result[5], result[6], result[7],
                             result[8], result[9], result[10], result[11],
                             result[12], result[13], result[14], result[15]];
            
            
            //SHA1
            NSData *sha1_data = [adId dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
            uint8_t digest[CC_SHA1_DIGEST_LENGTH];
            CC_SHA1(sha1_data.bytes, sha1_data.length, digest);
            NSMutableString* sha1 = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
            
            for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++)
                [sha1 appendFormat:@"%02x", digest[i]];
            
            adId = [NSString stringWithFormat:@"mmh_%@_%@",[md5 lowercaseString],sha1];
            //mmh_MD5_SHA1
        }
        return adId;
    }
#endif
    
    return nil;
}
...

WiFi MAC Address - Used for iOS Versions before 6

Some users may not have iOS version 6+. For these users, our preferred method for receiving the iOS ID is by hashing the WiFi MAC Address.

The WiFi MAC Address is 12 alphanumeric characters that are specific to that device and should be sent in the mmdid field using the MD5 and SHA1 hash and appending “mmh_” to generate a string with the format of mmh_[MD5]_[SHA1].

Example:

...mmdid=mmh_80B2AEF0134242A831D6025B0558BD84_4585EAA5E86BBD2E476320EB1D55E9B1A7BABA4F&..

Before hashing, the MAC Address should be all uppercase letters with colons.

The ID you send us will be case-sensitive (and character-sensitive). Please see the examples below.

Correct Formatting of the WifI MAC Address before hashing

...
04:0C:CE:E2:4F:16 – CORRECT - UPPER CASE letters and colon separators
...

Incorrect Formatting of the WiFi MAC Address before hashing

...
04:0c:ce:e2:4f:16 – INCORRECT - lower case letters
04-0c-ce-e2-4f-16 – INCORRECT - lower case letters and invalid separators
04-0C-CE-E2-4F-16 – INCORRECT - invalid separators 
...

For More Information