在Dart/Flutter中计算Dropbox content_hash遇问题求助
问题根源
你在第三步犯了关键错误:Dropbox要求拼接的是每个块哈希的原始二进制字节,而非把十六进制哈希字符串转换成ASCII二进制字符串。
你的toBinary方法把十六进制字符串(比如2a846fa6...)的每个字符转换成对应的ASCII二进制(比如字符'2'变成00110010),完全偏离了要求。正确做法是把每个十六进制哈希字符串解码成它对应的32字节二进制数据(SHA-256哈希本身是256位,即32字节),再直接拼接这些字节数组。
修正后的代码
首先需要引入convert包处理十六进制解码:
import 'package:convert/convert.dart';
然后替换第三步和第四步的错误代码:
/// Step 3: 拼接所有块哈希的原始二进制字节 final concatenatedBytes = <int>[]; for (final chunkHash in chunkHashes) { // 将十六进制字符串解码为原始二进制字节(每个哈希对应32字节) final binaryHash = hex.decode(chunkHash); concatenatedBytes.addAll(binaryHash); } /// Step 4: 计算拼接后字节的SHA-256哈希 final contentHash = getHash(concatenatedBytes); print(contentHash); // 现在会输出正确的485291fa0ee50c016982abbfa943957bcd231aae0492ccbaa22c58e3997b35e0
完整修正后的函数
import 'package:convert/convert.dart'; import 'package:crypto/crypto.dart'; import 'package:http/http.dart' as http; Future<void> getDropContentHash() async { String getHash(List<int> bytes) => sha256.convert(bytes).toString(); /// Nasa Milky Way Example: final response = await http.get(Uri.parse('https://www.dropbox.com/static/images/developers/milky-way-nasa.jpg')); final bytes = response.bodyBytes; /// Step 1: 分割文件为4MB块 final chunks = bytes.slices(4 * 1024 * 1024); print(chunks.length); // 3,符合预期 /// Step 2: 计算每个块的SHA-256哈希(十六进制格式) final chunkHashes = <String>[]; for(final chunk in chunks) { final blockHash = getHash(chunk); chunkHashes.add(blockHash); } print(chunkHashes); // 正确的块哈希 /// Step 3: 拼接所有块哈希的原始二进制字节 final concatenatedBytes = <int>[]; for (final chunkHash in chunkHashes) { final binaryHash = hex.decode(chunkHash); concatenatedBytes.addAll(binaryHash); } /// Step 4: 计算最终的content_hash final contentHash = getHash(concatenatedBytes); print(contentHash); // 输出正确值:485291fa0ee50c016982abbfa943957bcd231aae0492ccbaa22c58e3997b35e0 }
关键说明
- SHA-256哈希的本质是256位二进制数据,十六进制字符串只是它的可读性表示形式。Dropbox要求直接使用这个二进制数据拼接,而非对十六进制字符串做字符层面的转换。
hex.decode()会把每两个十六进制字符转换成一个字节,比如2a会被转换成字节0x2A(十进制42),这正是我们需要的原始哈希二进制数据。
内容的提问来源于stack exchange,提问作者Jared Anderton
相关产品推荐
相关产品推荐

