Objective c NSData中的NSString始终为空
我想用HMAC SHA512签署一个请求,但我似乎搞乱了NSData和NSString之间的编码和解码。我拼命想弄清楚到底是什么错了,但我似乎没有弄清楚 伪代码:Objective c NSData中的NSString始终为空,objective-c,macos,sha,hmac,nsstringencoding,Objective C,Macos,Sha,Hmac,Nsstringencoding,我想用HMAC SHA512签署一个请求,但我似乎搞乱了NSData和NSString之间的编码和解码。我拼命想弄清楚到底是什么错了,但我似乎没有弄清楚 伪代码: 我的实施: 以下是签名方法: +(NSString *)signRequestForParameterString:(NSString*)paramStr{ NSString *secret = @"7pgj8Dm6"; // secret is base64 encoded, so I decode it
我的实施: 以下是签名方法:
+(NSString *)signRequestForParameterString:(NSString*)paramStr{
NSString *secret = @"7pgj8Dm6";
// secret is base64 encoded, so I decode it
NSData *decodedSecret = [secret base64DecodedData];
NSString *decodedSecretString = [NSString stringWithUTF8String:[decodedSecret bytes]];
NSData *data = [paramStr dataUsingEncoding:NSUTF8StringEncoding];
NSString *dataString = [NSString stringWithUTF8String:[data bytes]];
return [self generateHMACSHA512Hash:decodedSecretString data:dataString];
}
以下是哈希函数:
+(NSString *)generateHMACSHA512Hash:(NSString *)key data:(NSString *)data{
const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];
unsigned char cHMAC[CC_SHA512_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA512, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC
length:sizeof(cHMAC)];
NSString *hash = [HMAC base64EncodedString];
return hash;
}
我很确定这是由于字符串的编码(decodedSecretString和dataString)<解码后的code>decodedSecretString(decoded base64)以ASCII编码。然而,当我调用散列方法时,我再次用ascii编码它,这将导致一个空错误。现在一切都让我困惑 您的密码无法解码为有效的UTF-8字符串,Java允许字符串中包含NUL字节,但当您将“Test\0消息”转换为C字符串并使用strlen时,其长度为4 像这样的方法应该会奏效:
+(NSString *)signRequestForParameterString:(NSString*)paramStr{
NSString *secret = @"7pgj8Dm6";
NSData *data = [paramStr dataUsingEncoding:NSUTF8StringEncoding];
return [self generateHMACSHA512Hash:[secret base64DecodedData] data:data];
}
+(NSString *)generateHMACSHA512Hash:(NSData *)key data:(NSData *)data{
unsigned char cHMAC[CC_SHA512_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA512, key.bytes, key.length, data.bytes, data.length, cHMAC);
NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
return [HMAC base64EncodedString];
}
在执行HMAC或其他加密函数时,您应该建立一些基本的方法/函数,这些方法/函数不首先处理字符串。然后可以创建包装器方法,以方便的方式对字符串数据进行解码/编码或摘要
+ (NSData *)dataBySigningData:(NSData *)data withKey:(NSData *)key
{
unsigned char cHMAC[CC_SHA512_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA512, [key bytes], [key length], [data bytes], [data lenght], cHMAC);
return [[NSData alloc] initWithBytes:cHMAC length:CC_SHA512_DIGEST_LENGTH];
}
+ (NSData *)dataBySigningMessage:(NSString *)message withKey:(NSData *)key
{
return [self dataBySigningData:[message dataUsingEncoding:NSUTF8StringEncoding]
withKey:[key dataUsingEncoding:NSUTF8StringEncoding]];
}
(注意:此代码未经测试,只是在文本编辑器中拼凑而成)
不要担心键或数据的字符串表示形式。然后您可以从那里开始,例如获取摘要的base64编码
加密函数不关心字符串或文本编码。他们关心字节。字符串(在C中,因为它们以null结尾)只是数据中可以表示的内容的子集。因此,处理字符串将受到严重限制。这需要检查大量代码。难道你不能稍微调试一下,弄清楚事情到底出了什么问题吗?如果你的秘密是Base64编码的,那么你应该对它进行解码,并将解码后的NSData传递给你的HMAC函数。不要将其转换回字符串。为什么要在
+signRequestForParameterString:
中将其转换回HMAC方法中的字节数组时,从NSString转换回NSData再转换回NSString?这有什么意义?只需将字符串传递给HMAC方法。您可能应该坚持使用UTF8,而不是ASCII,除非您知道您有ASCII文本,并且服务器无法理解UTF-8。难以置信!非常感谢你!
+(NSString *)signRequestForParameterString:(NSString*)paramStr{
NSString *secret = @"7pgj8Dm6";
NSData *data = [paramStr dataUsingEncoding:NSUTF8StringEncoding];
return [self generateHMACSHA512Hash:[secret base64DecodedData] data:data];
}
+(NSString *)generateHMACSHA512Hash:(NSData *)key data:(NSData *)data{
unsigned char cHMAC[CC_SHA512_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA512, key.bytes, key.length, data.bytes, data.length, cHMAC);
NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
return [HMAC base64EncodedString];
}
+ (NSData *)dataBySigningData:(NSData *)data withKey:(NSData *)key
{
unsigned char cHMAC[CC_SHA512_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA512, [key bytes], [key length], [data bytes], [data lenght], cHMAC);
return [[NSData alloc] initWithBytes:cHMAC length:CC_SHA512_DIGEST_LENGTH];
}
+ (NSData *)dataBySigningMessage:(NSString *)message withKey:(NSData *)key
{
return [self dataBySigningData:[message dataUsingEncoding:NSUTF8StringEncoding]
withKey:[key dataUsingEncoding:NSUTF8StringEncoding]];
}