【问题标题】:C# to Java Base64 and HmacSHA256 encryptionC# 到 Java Base64 和 HmacSHA256 加密
【发布时间】:2017-12-10 03:55:27
【问题描述】:

我在 C# 中有以下代码,它从 Base64 编码的字符串生成哈希值。

var hmacSha256 = new System.Security.Cryptography.HMACSHA256 { Key = Convert.FromBase64String(key) };

string verb = "post";
string resourceType = "docs";
string resourceId = "dbs/ToDoList/colls/Items";
string date = DateTime.UtcNow.ToString("R");

string payLoad = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}\n{1}\n{2}\n{3}\n{4}\n",
        verb.ToLowerInvariant(),
        resourceType.ToLowerInvariant(),
        resourceId,
        date.ToLowerInvariant(),
        ""
);

byte[] hashPayLoad = hmacSha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(payLoad));
string signature = Convert.ToBase64String(hashPayLoad);

string authToken = System.Web.HttpUtility.UrlEncode(String.Format(System.Globalization.CultureInfo.InvariantCulture, "type={0}&ver={1}&sig={2}",
    keyType,
    tokenVersion,
    signature));

这很好用,我想将它转换为我的 Android 应用程序的 Java 代码。我检查了这些来源的参考资料-

C# vs Java HmacSHA1 and then base64

c# and java - difference between hmacsha256 hash

并用Java编写以下代码-

String restServiceVersion = "2017-02-22";

String verb = "post";
String resourceType = "docs";
String resourceId = "dbs/ToDoList/colls/Items";

String dateString = org.apache.http.impl.cookie.DateUtils.formatDate(new Date(System.currentTimeMillis()));

String gmtIndex = "GMT";
int index = dateString.indexOf(gmtIndex);

String dateStringFinal = dateString.substring(0, index + 3).toLowerCase();

String payLoad = verb +"\n" + resourceType + "\n" + resourceId + "\n" + dateStringFinal + "\n\n";

System.out.println(payLoad);

String secretAccessKey = MASTER_KEY;
String data = payLoad;
byte[] secretKey = Base64.decode(secretAccessKey, Base64.DEFAULT);
SecretKeySpec signingKey = new SecretKeySpec(secretKey, "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(signingKey);
byte[] bytes = data.getBytes("UTF-8");
byte[] rawHmac = mac.doFinal(bytes);

String authToken = "type=master&ver=1.0&sig=" + Base64.encodeToString(rawHmac, Base64.DEFAULT);

Java 中生成的authToken 值与 C# 不匹配。 Base64解码生成的字节数组也不同。

我不确定这是否是正确的方法。有人可以看看吗?我只需要为我的 Android 应用程序将上述 C# 代码转换为 Java。

【问题讨论】:

  • 所以值不匹配。多么丰富的信息..... 不是
  • 如果base64解码后的key字节不同,那么sha256 hash肯定也会不同。您是否绝对 100% 确定源 base64 编码的密钥在两者中是相同的?您能否向我们展示给定输入您在每个平台下获得的输出? (如果您使用的确切密钥仅用于本地测试目的,您可以使用它)。
  • @DylanNicholson 是的,源密钥和其他参数相同。只是担心我是否正确构建它们。
  • 我会说,不管键是否不同,鉴于您的输入文本包含基于当前时间的日期,即使在同一平台上,哈希值也总是会不同!您确定 org.apache.http.impl.cookie.DateUtils.formatDate 生成与 .ToString("R") 相同的格式吗?但是,如果您不打算发布有关所见内容的更多信息,我怀疑有人会为您解决问题。
  • @DylanNicholson 是的。但实际上,为了调试,我已经替换并硬编码了相同的日期值。甚至字节数组的初始值——byte[] secretKey = Base64.decode(secretAccessKey, Base64.DEFAULT);不同于 C#- Convert.FromBase64String(key)

标签: java c# android base64 sha256


【解决方案1】:

最可能的解释:您的 BASE64 字符串中嵌入了不可见的 unicode 字符(例如“零宽度非连接符”)。一个平台在 base-64 解码时会去除这些,而另一个则不会,从而导致不同的键。

【讨论】:

  • 鉴于他提供的所有信息(阅读上面的评论线程),这几乎肯定是解释他观察到的行为的唯一答案(注意,从技术上讲,除了“有人可以接受看看?”)。
猜你喜欢
  • 1970-01-01
  • 2011-12-05
  • 1970-01-01
  • 2020-03-04
  • 1970-01-01
  • 2011-05-24
  • 1970-01-01
  • 2012-10-25
相关资源
最近更新 更多