Android base64哈希与使用C#脚本的服务器端哈希不匹配
我正在Android应用程序中使用HMAC SHA256创建base64哈希。并将其发送到服务器上,以便与服务器端哈希匹配。Android base64哈希与使用C#脚本的服务器端哈希不匹配,c#,android,ios,C#,Android,Ios,我正在Android应用程序中使用HMAC SHA256创建base64哈希。并将其发送到服务器上,以便与服务器端哈希匹配。 下面是教程 工作Android代码: public String getHash(String data,String key) { try { String secret = key; String message = data; Mac sha256_HMAC = Mac.getInstance("
下面是教程 工作Android代码:
public String getHash(String data,String key)
{
try
{
String secret = key;
String message = data;
Mac sha256_HMAC = Mac.getInstance("HmacMD5");
SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacMD5");
sha256_HMAC.init(secret_key);
String hash = Base64.encodeBase64String(sha256_HMAC.doFinal(message.getBytes()));
System.out.println(hash);
return hash;
}
catch (Exception e){
System.out.println("Error");
}
}
服务器代码采用C#脚本,其格式如下所示
using System.Security.Cryptography;
namespace Test
{
public class MyHmac
{
private string CreateToken(string message, string secret)
{
secret = secret ?? "";
var encoding = new System.Text.ASCIIEncoding();
byte[] keyByte = encoding.GetBytes(secret);
byte[] messageBytes = encoding.GetBytes(message);
using (var hmacsha256 = new HMACSHA256(keyByte))
{
byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
return Convert.ToBase64String(hashmessage);
}
}
}
}
但安卓端生成的哈希键与服务器端不匹配,下面是生成与c#代码相同的目标c代码
目标c代码:
#import "AppDelegate.h"
#import <CommonCrypto/CommonHMAC.h>
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSString* key = @"secret";
NSString* data = @"Message";
const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];
unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSData *hash = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
NSLog(@"%@", hash);
NSString* s = [AppDelegate base64forData:hash];
NSLog(s);
}
+ (NSString*)base64forData:(NSData*)theData
{
const uint8_t* input = (const uint8_t*)[theData bytes];
NSInteger length = [theData length];
static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t* output = (uint8_t*)data.mutableBytes;
NSInteger i;
for (i=0; i < length; i += 3) {
NSInteger value = 0;
NSInteger j;
for (j = i; j < (i + 3); j++) {
value <<= 8;
if (j < length) { value |= (0xFF & input[j]);
}
}
NSInteger theIndex = (i / 3) * 4; output[theIndex + 0] = table[(value >> 18) & 0x3F];
output[theIndex + 1] = table[(value >> 12) & 0x3F];
output[theIndex + 2] = (i + 1) < length ? table[(value >> 6) & 0x3F] : '=';
output[theIndex + 3] = (i + 2) < length ? table[(value >> 0) & 0x3F] : '=';
}
return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
}
@end
#导入“AppDelegate.h”
#进口
@实现AppDelegate
-(无效)ApplicationIDFinishLaunching:(NSNotification*)通知
{
NSString*key=@“secret”;
NSString*数据=@“消息”;
const char*cKey=[key cStringUsingEncoding:NSASCIIStringEncoding];
常量字符*cData=[数据cStringUsingEncoding:NSASCIIStringEncoding];
无符号字符cHMAC[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256、cKey、strlen(cKey)、cData、strlen(cData)、cHMAC);
NSData*hash=[[NSData alloc]initWithBytes:cHMAC长度:sizeof(cHMAC)];
NSLog(@“%@”,哈希);
NSString*s=[AppDelegate base64forData:hash];
NSLog(s);
}
+(NSString*)base64forData:(NSData*)数据
{
常量uint8_t*输入=(常量uint8_t*)[数据字节];
NSInteger长度=[数据长度];
静态字符表[]=“abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzo123456789+/=”;
NSMutableData*数据=[NSMutableData数据长度:((长度+2)/3)*4];
uint8_t*输出=(uint8_t*)data.mutableBytes;
恩森特格尔一世;
对于(i=0;i>12)&0x3F];
输出[索引+2]=(i+1)>6)和0x3F]:'=';
输出[索引+3]=(i+2)>0)和0x3F]:'=';
}
return[[NSString alloc]initWithData:数据编码:NSASCIIStringEncoding];
}
@结束
请帮我解决这个问题,
提前谢谢
我已经通过将HmacSHA256更改为HmacMD5解决了这个问题,并给出了与C#代码相同的哈希值
我已经用工作代码更新了我的问题。请在android
secret中检查它。getBytes
可能会得到UTF-16字节,请检查结果的长度。通常情况下,将这些函数分离到单独的语句中以便于调试
不是答案,而是一个更简单的Obj-C实现的演示,并提供了哈希和Base64值:
NSString* key = @"secret";
NSString* data = @"Message";
NSData *keyData = [key dataUsingEncoding:NSASCIIStringEncoding];
NSData *dataData = [data dataUsingEncoding:NSASCIIStringEncoding];
NSMutableData *hash = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, keyData.bytes, keyData.length , dataData.bytes, dataData.length, hash.mutableBytes);
NSLog(@"hash: %@", hash);
NSString* s = [hash base64EncodedStringWithOptions:0];
NSLog(@"s: %@", s);
输出:
hash: <aa747c50 2a898200 f9e4fa21 bac68136 f886a0e2 7aec70ba 06daf2e2 a5cb5597>
s: qnR8UCqJggD55PohusaBNviGoOJ67HC6Btry4qXLVZc=
hash:
s:QNR8UCQJGGD55POHUSANBIVIGOOJ67HC6BTRY4QXLVZC=
我怀疑这是一个编码问题。
在一个示例中,您指定字符串在转换为字节数组时应使用ASCII编码。在另一个示例中,您未指定编码。
如果默认编码不是ASCII,则意味着字节数组将不同,从而导致不同的哈希结果。请注意,自从iOS 7和OSX 10.9以来,有一种编码和解码Base64的方法:
base64EncodedDataWithOptions:
和base64EncodedStringWithOptions:
。您得到的Androi的值是多少d、 请参阅psudo答案中Objective-C的输出。这似乎只是一个Android问题。@Zaph在Objective-C中的输出长度为24,在Android端的输出长度为42。请参阅我的答案,它的输出长度为42。在您的示例中提供NSLog语句的输出,编辑您的问题并添加这些值。@Zaph谢谢您的帮助,我是have解决了问题并对其进行了更新。可能不是编码,示例中有ASCII字符。但可能是AndroidgetBytes
返回UTF-16(unichar)字节。在两种平台上使用相同的编码。例如,在.NET端使用UTF8Encoding而不是Asciencoding,然后在Java端使用secred.getBytes(Charsets.UTF_8)。这意味着双方将使用相同的编码,因此您将从文本中获得相同的字节数组。(或者使用UTF16,或任何您喜欢的其他编码,只要确保在两个系统上都是相同的)。@BrianO“Byrne current我在双方使用相同的编码,这是一种密码。因此我无法找到问题。