2

我正在将 iOS 应用程序的一部分移植到 Android,但在将 iOS 中的以下签名生成代码移植到 Android 时遇到问题。iOS代码是:

+ (NSString *)hashedBase64ValueOfData:(NSString *) data WithSecretKey:(NSString*)secret {
    // ascii convirsion
    const char *cKey  = [secret cStringUsingEncoding:NSASCIIStringEncoding];
    const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];

    // HMAC Data structure initializtion
    unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
    CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);

    // Gerating hased value
    NSData *da =  [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];

    return [da base64EncodedString];// conversion to base64 string & returns
}

我编写并尝试过的 Android Java 代码是:

private static String hashedBase64ValueOfDataWithSecretKey(String data, String secret) {
    try {
        SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(), HMAC_SHA1_ALGORITHM);
        Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
        mac.init(signingKey);
        byte[] rawHmac = mac.doFinal(data.getBytes());
        return Base64.encodeToString(rawHmac, 0);

    } catch (Exception e) {
        e.printStackTrace();
    }

    return null;
}

经测试,Android 函数输出的内容与 iOS 函数不同(输入相同),我不知道为什么。

4

2 回答 2

2

不是这方面的专家,但NSASCIIStringEncoding似乎暗示您想要datasecret解释为 ASCII,而String.getBytes()默认使用默认字符集(即 UTF-8)。

您可能需要使用不同的字符集

data.getBytes(StandardCharsets.US_ASCII);
secret.getBytes(StandardCharsets.US_ASCII);

对于 Java pre-1.7,您需要使用它并捕获UnsupportedEncodingException

data.getBytes("US-ASCII");
secret.getBytes("US-ASCII");
于 2013-08-14T20:17:57.530 回答
0

您可能会使用额外的 org.apache.commons.codec.binary.Base64。谷歌一下找到它,然后你可以找到下面的代码。我认为散列值将由“私钥”生成,并附加在“公钥”后面,并与“http-head”一起发送到服务器。如果没有,您可以删除它们。无论如何,代码可能会给你一些建议。:)

private String getAppendedHeader(String str) {
    try {
        String hash = getHash(str);

        String signature = new String(Base64.encodeBase64(hash.getBytes()));
        StringBuilder sb = new StringBuilder();
        sb.append(PUBLIC_KEY).append(' ').append(signature);
        return sb.toString();
    } catch (NoSuchAlgorithmException _e) {
        LL.e("Get mac error: " + _e.getMessage());
        return null;
    } catch (InvalidKeyException _e) {
        LL.e("Init mac error: " + _e.getMessage());
        return null;
    }
}


private String getHash(String str) throws NoSuchAlgorithmException, InvalidKeyException {
    Mac mac = Mac.getInstance("HmacSHA256");
    SecretKeySpec secret = new SecretKeySpec(PRIVATE_KEY.getBytes(), "HmacSHA256");
    mac.init(secret);
    byte[] digest = mac.doFinal(str.getBytes());
    BigInteger hash = new BigInteger(1, digest);
    String hmac = hash.toString(16);
    if (hmac.length() % 2 != 0) {
        hmac = "0" + hmac;
    }
    return hmac;
}
于 2013-08-14T20:14:49.273 回答