在iOS中生成SHA256

在iOS中生成SHA256,ios,windows-phone,sha256,hmac,Ios,Windows Phone,Sha256,Hmac,我尝试在iOS中使用包含以下数据的库生成SHA256: 字符串:Amount=50&bilerid=59&ChannelID=2&Context=34 | check | test&ReturnURL=https://uat.myfatoora.com/ReceiptPOC.aspx&TxnRefNum=000000000020003&UserName=DCS 密钥:71DD0F73AFFB47825FF9864DDE95F3B 结果为409DC622B3BEF5C9FC46E45C321011

我尝试在iOS中使用包含以下数据的库生成SHA256:

字符串:Amount=50&bilerid=59&ChannelID=2&Context=34 | check | test&ReturnURL=https://uat.myfatoora.com/ReceiptPOC.aspx&TxnRefNum=000000000020003&UserName=DCS

密钥:71DD0F73AFFB47825FF9864DDE95F3B

结果为409DC622B3BEF5C9FC46E45C321011FCB4536D3A55833316FE0DC8154B3EA34

我认为这是正确的。但是,Windows对应程序正在使用以下代码生成SHA256:

Windows Phone Source Code:

public static string HmacSha256(string secretKey, string value)
    {
        var msg = CryptographicBuffer.ConvertStringToBinary(value, BinaryStringEncoding.Utf8);
        byte[] convertedHash = new byte[secretKey.Length / 2];

        for (int i = 0; i < secretKey.Length / 2; i++)
        {
            convertedHash[i] = (byte)Int32.Parse(secretKey.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
        }

        // Create HMAC.
        var objMacProv = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha256);
        CryptographicHash hash = objMacProv.CreateHash(convertedHash.AsBuffer());

        hash.Append(msg);
        return CryptographicBuffer.EncodeToHexString(hash.GetValueAndReset());

    }

Windows代码接受字符串,将其解释为十六进制数,并将每次两个字符转换为一个字节

你的Mac代码最喜欢的是字符串。由于密钥以71开头,windows代码将其作为一个单字节,值0x71=129,Mac代码将其作为两个字节,值“7”=55,“1”=49


你所需要做的就是在Mac上转换字节,就像在Windows上一样。你可能不得不做一些不可思议的事情,看看Mac库的源代码,看看它是如何进行实际的哈希计算的

这里的关键是您需要将您的密码(十六进制字符串)转换为NSData。换句话说,NSData字节流看起来就像是秘密

这应该满足您的要求:

    // Hex string to NSData conversion from here http://stackoverflow.com/questions/7317860/converting-hex-nsstring-to-nsdata
    NSString *secret = @"71DD0F73AFFBB47825FF9864DDE95F3B";
    NSData *dataIn = [@"Amount=50&BillerID=59&ChannelID=2&Context=34|check|test&ReturnURL=https://uat.myfatoora.com/ReceiptPOC.aspx&TxnRefNum=000000000020003&UserName=DCS" dataUsingEncoding:NSUTF8StringEncoding];
    NSMutableData *macOut = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];

    secret = [secret stringByReplacingOccurrencesOfString:@" " withString:@""];
    NSMutableData *secretData = [[NSMutableData alloc] init];
    unsigned char whole_byte;
    char byte_chars[3] = {'\0','\0','\0'};
    int i;
    for (i=0; i < [secret length]/2; i++) {
        byte_chars[0] = [secret characterAtIndex:i*2];
        byte_chars[1] = [secret characterAtIndex:i*2+1];
        whole_byte = strtol(byte_chars, NULL, 16);
        [secretData appendBytes:&whole_byte length:1];
    }

    CCHmac(kCCHmacAlgSHA256, secretData.bytes, secretData.length, dataIn.bytes, dataIn.length, macOut.mutableBytes);

    NSMutableString *stringOut = [NSMutableString stringWithCapacity:macOut.length];
    const unsigned char *macOutBytes = macOut.bytes;

    for (NSInteger i=0; i<macOut.length; ++i) {
        [stringOut appendFormat:@"%02x", macOutBytes[i]];
    }

    NSLog(@"dataIn: %@", dataIn);
    NSLog(@"macOut: %@", macOut);
    NSLog(@"stringOut: %@", stringOut);
可以使用此扩展名将十六进制字符串转换为数据

使用以下方法:

    let secret = "71DD0F73AFFBB47825FF9864DDE95F3B"
    let value = "Amount=50&BillerID=59&ChannelID=2&Context=34|check|test&ReturnURL=https://uat.myfatoora.com/ReceiptPOC.aspx&TxnRefNum=000000000020003&UserName=DCS"

    print("\(generateHMAC(key: secret, data: value))")
您的输出应该是94a20ca39c8487c7763823ec9c918d9e38ae83cb741439f6d129bcdef9edba73

您需要在桥接标头中导入。

进口 +NSString*hmacSHA256EncryptString{ NSString*参数secret=@输入密钥; NSString*plainString=@输入加密内容字符串; const char*secretKey=[参数secret cStringUsingEncoding:NSUTF8StringEncoding]; const char*plainData=[plainString cStringUsingEncoding:NSUTF8StringEncoding]; 无符号字符cHMAC[CC_SHA256_DIGEST_LENGTH]; CCHmackCCHmacAlgSHA256,secretKey,strlensecretKey,plainData,strlenpaindata,cHMAC; NSData*HMACData=[NSData dataWithBytes:cHMAC length:sizeofcHMAC]; 常量无符号字符*缓冲字符=常量无符号字符*[HMACData字节]; NSMutableString*hmacString=[NSMutableString stringWithCapacity:HMACData.length*2]; 对于int i=0;i}您没有显示任何有关iOS端的代码。另外,SHA256和HMAC-SHA256是不同的东西。@SamiKuhmonen:我已经添加了iOS源代码;它正在使用奥术库。我尝试过这样做`对于0中的I…secretKey.length/2{let range=NSMakeRangei*2,如果range.location<32{convertedHash.appendDatasecretKey.SubstringWithRange.DataUsingEncoding NSUTF8StringEncoding!}`但这没用。你可以发布一些代码吗?哦,你需要导入,对不起,这是Obj-C,但是你应该可以用Swift做同样的操作,CCHmac在那里可用。这里是一个链接到一些参考做,嗨,谢谢你的回答。请告诉我'let dataIn=data.datausing:.utf8!中的data.data是什么!作为NSData`因为它给了我错误。我假设您正在将字符串转换为NSData。非常感谢您@MobileBen。这就是我需要的。
// http://stackoverflow.com/questions/29799361/generate-a-hmac-swift-sdk8-3-using-cchmac
func generateHMAC(key: String, data: String) -> String {
    let keyData = key.dataFromHexadecimalString()! as NSData
    let dataIn = data.data(using: .utf8)! as NSData
    var result: [CUnsignedChar]
    result = Array(repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
    CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), keyData.bytes, keyData.length, dataIn.bytes, dataIn.length, &result)

    let hash = NSMutableString()
    for val in result {
        hash.appendFormat("%02hhx", val)
    }

    return hash as String
}
// Modified slightly http://stackoverflow.com/questions/26501276/converting-hex-string-to-nsdata-in-swift
extension String {

    func dataFromHexadecimalString() -> Data? {
        var data = Data(capacity: characters.count / 2)

        let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive)
        regex.enumerateMatches(in: self, options: [], range: NSMakeRange(0, characters.count)) { match, flags, stop in
            let byteString = (self as NSString).substring(with: match!.range)
            var num = UInt8(byteString, radix: 16)
            data.append(&num!, count: 1)
        }

        return data
    }
}
    let secret = "71DD0F73AFFBB47825FF9864DDE95F3B"
    let value = "Amount=50&BillerID=59&ChannelID=2&Context=34|check|test&ReturnURL=https://uat.myfatoora.com/ReceiptPOC.aspx&TxnRefNum=000000000020003&UserName=DCS"

    print("\(generateHMAC(key: secret, data: value))")