How to add digest from sha256 to string in flutter?

1,717

Solution 1

When you print digest, the print method will call digest.toString(), which is implemented to return a string of the digest bytes using a hexadecimal representation. If you want the same thing you have several options:

  • Call digest.toString() explicitly (or implicitly)
final digestHex = digest.toString(); // explicitly
final digestHex = '$digest';         // implicitly
  • Map the byte array to its hexadecimal equivalent
final digestHex = digest.bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join();
  • Use the convert package (this is what the crypto package does)
import 'package:convert/convert.dart';

...

final digestHex = hex.encode(digest.bytes);

The reason you are getting an error using utf8.decode is that your digest isn't an encoded UTF-8 string but a list of bytes that for all intents and purposes are completely random. You are trying to directly convert the bytes into a string, and doing so is easier if you can assume that they already represent a valid string. With the byte output from a hashing algorithm, though, you cannot safely make such an assumption.

However, if for some reason you still want to use this option, use the second optional parameter for utf8.decode to force it to try and decode the bytes anyway:

final digestString = utf8.decode(bytes, allowMalformed: true);

For reference, a byte list of [1, 255, 47, 143, 6, 80, 33, 202] results in "�/�P!�" where "�" represents an invalid/control character. You do not want to use this option, especially where the string will become part of a URL (as it's virtually guaranteed that the resulting string will not be web-safe).

Solution 2

For the hexadecimal representation of a Digest object, please explicitly call Digest.toString() (though in formatted strings, i.e. "url${digest}", this is done for you implicitly).

I'm frankly not familiar with String.fromCharCode, but I think it's looking for UTF-16 and not UTF-8 bits. I wrote a terminal example to show this, and how the outputs differ.

import 'dart:core';
import 'dart:convert';
import 'package:crypto/crypto.dart';

void main() {

  const String password = "mypassword";

  // hash the password
  var bytes = utf8.encode(password);
  var digest = sha256.convert(bytes);

  // different formats
  var bytesDigest = digest.bytes;
  var hexDigest = digest.toString();

  String url = "http://example_api.php?hash=";

  print(url + hexDigest);
  print(url + String.fromCharCodes(bytesDigest));

}

Output:

> dart test.dart
http://example_api.php?hash=89e01536ac207279409d4de1e5253e01f4a1769e696db0d6062ca9b8f56767c8
http://example_api.php?hash=à6¬ ry@Ö,©¸õggÈ
Share:
1,717
Sprowk
Author by

Sprowk

Updated on December 17, 2022

Comments

  • Sprowk
    Sprowk over 1 year

    I'm passing password into sha256. I successfully create sha256 and can also print it. The problem begins when I'm trying to convert digest.bytes into a string and append it.

    import 'package:crypto/crypto.dart';
    
    var url = "http://example_api.php?";
    url += '&hash=';
    
    // hash the password
    var bytes = utf8.encode(password);
    var digest = sha256.convert(bytes);
    print("Digest as hex string: $digest");
    
    url += String.fromCharCodes(digest.bytes);
    

    This is printed: Digest as hex string: 03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4

    This is appended to url: ¬gBóá\vá¥âUðg6#ȳ´Eùx×ÈFô

    What am I doing wrong? I also tried utf8.decode method but using it gives me an error.