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;
答案 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;
}