c#windows store app和Objective-c iOS之间的SHA1哈希差异

时间:2015-07-07 07:52:12

标签: c# ios objective-c windows-store-apps sha1

Surface Pro上的我的Windows应用商店应用使用SHA1向服务器发送散列密码。我想为iOS应用程序做同样的事情,但我得到不同的结果,我只是不知道为什么。

我在尝试将NSStrings转换为cString时使用了不同的编码(NSASCII UTF8 UniCode),但没有占上风。

c#Windows应用商店应用 - Surface专业人员

/// <summary>
    /// Literal copy of the values from web config machinekey
    /// </summary>
    const String validationKey = "6DB51F17C529AD3CABEC50B3C89CB21F4F1422F58A5B42D0E8DB8CB5CDA146511891C1BAF47F8D29401E3400267682B202B7DA146511891C1BAF47F8D29401E3";

    public static string HmacSha1(string baseString)
    {
        var crypt = MacAlgorithmProvider.OpenAlgorithm("HMAC_SHA1");
        var buffer = CryptographicBuffer.CreateFromByteArray(Encoding.Unicode.GetBytes(baseString));
        var keyBuffer = Windows.Security.Cryptography.CryptographicBuffer.CreateFromByteArray(HexToByte(validationKey));
        var key = crypt.CreateKey(keyBuffer);
        var sigBuffer = CryptographicEngine.Sign(key, buffer);
        string signature = CryptographicBuffer.EncodeToBase64String(sigBuffer);
        return signature;
    }

    //
    // HexToByte
    //   Converts a hexadecimal string to a byte array. Used to convert encryption
    // key values from the configuration.
    //
    private static byte[] HexToByte(string hexString)
    {
        byte[] returnBytes = new byte[hexString.Length / 2];
        for (int i = 0; i < returnBytes.Length; i++)
            returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
        return returnBytes;
    }

Objective-c iOS

//Hash password
NSString *secret = @"6DB51F17C529AD3CABEC50B3C89CB21F4F1422F58A5B42D0E8DB8CB5CDA146511891C1BAF47F8D29401E3400267682B202B7DA146511891C1BAF47F8D29401E3";
NSString *data = password;
const char *cKey = [secret cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];
unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
NSString *signature = [HMAC base64EncodedStringWithOptions:0];


NSString *clientPassword = signature;

1 个答案:

答案 0 :(得分:0)

所以一些天才帮助我弄明白了。在c#代码中,密码使用Unicode进行编码,如下所示:

Encoding.Unicode.GetBytes(baseString)

这意味着我应该将Objective-C中的NSASCII编码行更改为:

const char *cPassword = [password cStringUsingEncoding:NSUnicodeStringEncoding];

现在有些棘手。 Unicode编码一个字符串,如&#39; Welkom123&#39;像这样:W/0e/0l/0k/0o/0m/01/02/03/0。这意味着我无法使用strlen(cData)来确定cData的长度,因为它会在遇到/0时停止计数,因此整个时间长度都是错误的。我必须将strlen(cData)替换为(password.length * 2)

但即便如此,结果仍然不对。密钥必须像c#代码一样成为十六进制数据。然后应该使用NSData来创建CCHmac。此代码使用十六进制值将NSString转换为NSData:

int len = (int)([inputString length] / 2);    // Target length
unsigned char *buf = malloc(len);
unsigned char *whole_byte = buf;
char byte_chars[3] = {'\0','\0','\0'};

int i;
for (i=0; i < [inputString length] / 2; i++) {
    byte_chars[0] = [inputString characterAtIndex:i*2];
    byte_chars[1] = [inputString characterAtIndex:i*2+1];
    *whole_byte = strtol(byte_chars, NULL, 16);
    whole_byte++;
}

NSData *data = [NSData dataWithBytes:buf length:len];
free( buf );
return data;

最后总代码如下所示:

-(NSDictionary *)authenticateWithUsername:(NSString *)userName andPassword:(NSString *)password andSyncUrl:(NSString *)syncUrl
{
NSString *key = @"6DB51F17C529AD3CABEC50B3C89CB21F4F1422F58A5B42D0E8DB8CB5CDA146511891C1BAF47F8D29401E3400267682B202B7DA146511891C1BAF47F8D29401E3";
NSData *data = [self stringToHexData:key];
const char *cPassword = [password cStringUsingEncoding:NSUnicodeStringEncoding];
unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA1, data.bytes, data.length, cPassword, (password.length * 2), cHMAC);
NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
NSString *hashedPassword = [HMAC base64EncodedStringWithOptions:0];

NSString *clientPassword = hashedPassword;

// some code here left out for readability sake

return dict;
}

- (NSData *) stringToHexData:(NSString *)inputString
{
int len = (int)([inputString length] / 2);    // Target length
unsigned char *buf = malloc(len);
unsigned char *whole_byte = buf;
char byte_chars[3] = {'\0','\0','\0'};

int i;
for (i=0; i < [inputString length] / 2; i++) {
    byte_chars[0] = [inputString characterAtIndex:i*2];
    byte_chars[1] = [inputString characterAtIndex:i*2+1];
    *whole_byte = strtol(byte_chars, NULL, 16);
    whole_byte++;
}

NSData *data = [NSData dataWithBytes:buf length:len];
free( buf );
return data;
}