【问题标题】:Signing a message with hmac and sha256 in dart在 dart 中使用 hmac 和 sha256 签署消息
【发布时间】:2018-09-24 16:34:54
【问题描述】:

我尝试在消息上使用 base64 解码的密钥生成 sha256 HMAC。我想使用飞镖语言。在 python 中,我可以使用以下代码:

# PYTHON CODE
import hmac, hashlib, base64
...
message = 'blabla'
secret = 'DfeRt[...]=='
secret_b64 = base64.b64decode(secret)
signature = hmac.new(secret_b64, message, hashlib.sha256)
signature_b64 = signature.digest().encode('base64').rstrip('\n')

这是我对 dart 的尝试:

// DART CODE
import 'package:crypto/crypto.dart';
import 'dart:convert';
...
String message = 'blabla';
String secret = 'DfeRt[...]=='
var secret_b64 = BASE64.decode(secret);
var hmac = new Hmac(sha256, secret_b64);
// what now?

但是我不知道该怎么做。我发现了一些旧的示例代码,如下所示

var message_byte = UTF8.encode(message);
hmac.add(message_byte);

但是,Hmac 类中不再存在“add”方法。我也试过这个,但我不确定这是否正确

var message_byte = UTF8.encode(message);    
var signature = hmac.convert(message_byte);
var signature_b64 = BASE64.encode(signature.bytes);

谁能帮帮我?

【问题讨论】:

  • 阅读文档,发现旧的示例代码不一样。
  • 确实如此,但只有在您知道自己在寻找什么的情况下,阅读文档才会有所帮助。我想我对 hmac 和 sha256 的概念也有一些麻烦。这就是为什么我不知何故迷路了。例如,我不太明白 Hmac 类的哪些新方法取代了旧的“add”方法。这就是我写这个问题的原因。
  • 我收到的最好的编码建议是 Rick 在计算机中心的一个晚上。我问 Rick 如何使用系统命令,他告诉我阅读手册,我这样做改变了我的开发人员生活。有时需要花几天时间(每天8小时)学习,在那些你不明白的事情上,你的情况是HAMCSHA-256Dart。随着您学习的深入,您将了解自己在寻找什么。
  • 是的,但是从专家的例子和指导下学习肯定比阅读理论更有效。特别是,如果你只是玩一点。当然,如果你已经知道风是怎么吹的,那么阅读概念和深入研究事物是非常好的。然后,当您是专家时,有人会说:rtfm。但感谢您的智慧。

标签: dart base64 sha256 hmac


【解决方案1】:

如果您有完整的“消息”可用,则只需调用 convert()。如果消息很大或者是碎片,那就分块处理。

你的例子很简单,一步一步说出来。

  String base64Key = 'DfeRt...';
  String message = 'blabla';

  List<int> messageBytes = utf8.encode(message);
  List<int> key = base64.decode(base64Key);
  Hmac hmac = new Hmac(sha256, key);
  Digest digest = hmac.convert(messageBytes);

  String base64Mac = base64.encode(digest.bytes);

请阅读Effective Dart 指南。注意常量现在是小写的,Dart 中的变量使用驼峰式,等等

【讨论】:

  • 非常感谢您的回答。为什么方法 'convert' 需要 List 类型的参数而不是 String?为了使其更通用,以便可以对任何类型的数据进行签名?
  • 是的,哈希和 MAC 对字节数组起作用,因此字符串需要首先使用编码转换为字节数组。 UTF-8 可能是最流行的,但还有很多其他的,例如 UTF-16(具有两个字节序)或 ISO 8859-1。显然,您的消息的接收者必须使用与您的 MAC 相同的编码来匹配!
【解决方案2】:

在我最近的项目中,我必须使用 hmac 签署一个调用 API 的请求。这是我所做的。希望这对你也有帮助。

import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:crypto/crypto.dart';

String getHmacAuthHeader({
  @required final String inputUrl,
  @required final dynamic inputJsonContent,
  @required final String appId,
  @required final String appSecrets,
  final String method = "POST",
}) {
  final url = _encodeUrl(inputUrl);
  final seconds =
      (DateTime.now().millisecondsSinceEpoch / 1000).round().toString();
  final nonce = "N${DateTime.now().millisecondsSinceEpoch}";

  final contentHash = _getMd5HashInBase64FromJson(inputJsonContent);

  final signature = "$appId$method$url$seconds$nonce$contentHash";

  final signatureHmacHashBase64 = _getHmacHashInBase64FromString(appSecrets, signature);

  final token = "$appId:$signatureHmacHashBase64:$nonce:$seconds";

  return "hmacauth $token";
}

String _encodeUrl(String url) {
  if (!url.startsWith("/")) {
    url = "/$url";
  }
  return Uri.encodeComponent(url).toLowerCase();
}

String _getMd5HashInBase64FromJson(dynamic json) {
  final jsonString = jsonEncode(json);
  final jsonStringBytes = Utf8Encoder().convert(jsonString);

  final hashBytes = md5.convert(jsonStringBytes).bytes;
  final hashBase64 = base64Encode(hashBytes);
  return hashBase64;
}

String _getHmacHashInBase64FromString(String key, String data){
  final keyBytes = Utf8Encoder().convert(key);
  final dataBytes = Utf8Encoder().convert(data);

  final hmacBytes = Hmac(sha256, keyBytes)
      .convert(dataBytes)
      .bytes;

  final hmacBase64 = base64Encode(hmacBytes);
  return hmacBase64;
}

【讨论】:

    猜你喜欢
    • 2018-07-05
    • 2018-08-06
    • 2016-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-21
    相关资源
    最近更新 更多