How to add digest from sha256 to string in flutter? - flutter

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.

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).

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È

Related

different in signature in Dart & node

am trying to make a signature for a HTTP request ,
using flutter/dart for the app and the server in NodeJs
but i have a problem there is little different between the two signature
any idea what cause that
EEFSxb_coHvGM-69RhmfAlXJ9J0= //signature in dart
EEFSxb/coHvGM+69RhmfAlXJ9J0= //signature in nodejs
signature.dart
var key = "key";
var data = "data";
List<int> signingKey = utf8.encode("key");
List<int> signatureBaseString = utf8.encode("data");
var hmacSha1 = Hmac(sha1, signingKey);
var digest = hmacSha1.convert(signatureBaseString);
var hashInBase = base64Url.encode(digest.bytes);
print(hashInBase) ; // result : EEFSxb_coHvGM-69RhmfAlXJ9J0=
signature.js
var data = "data" ;
var key = "key" ;
var output = encodeURIComponent(data);
var keyO = encodeURIComponent(key);
var hashed = CryptoJS.HmacSHA1(output , keyO);
var hashInBase = CryptoJS.enc.Base64.stringify(hashed);
console.log(hashInBase); // result : EEFSxb/coHvGM+69RhmfAlXJ9J0=
There are two styles of Base64 encoding which use slightly different character sets for the 64 characters. (You get 52 from the upper and lower case letters and ten more from the numbers, so a couple more ascii chars are needed to make up the 64 - plus the special trailing equals.)
The / and + characters have special meanings in URLs, so can be replaced in the alternative "URL safe" encoding with _ and -. Note also that the trailing equals can be dropped.
It seems you may be trying to compare base64 encoded strings to test for equality. It's safer to decode from base 64 and compare the byte arrays.
Anyway, to solve you problem, don't use the Dart URL safe version, use the regular version: base64.encode()

Convert double value to List<Int> in Dart

I'm using flutter_blue to communicate with a bluetooth device. I need to pass a double value to the bluetooth device using the flutter_blue write() method.
The value must be passed to the method as a list of integers which is supposed to represent a list of bytes as far as i understand it.
The flutter_blue write method:
Future<Null> write(
List<int> value,
{bool withoutResponse = false}
)
Is there a way to convert a double value to a list of integers that represents the double value as a list of bytes in order to pass it to flutter_blues write method?
For example:
double value = 10.52;
List<Int> convertedValue = someConversionMethod(value);
await bluetoothCharacteristic.write(convertedValue);
With Bluetooth it is normal to pass information as a list of bytes(Uint8List). The solution for float value is to have an expected exponent. There is more detail in the GATT Specification Supplement 4 especially in section 2 "Values and represented values"
If the number is large enough it will need to be converted to bytes in little endian format. As an example:
import 'dart:typed_data';
import 'dart:math';
void main() {
double value = 10.52;
var rawValue = value * pow(10, 2); // multiply value to remove decimal places
print('Raw value to send: $rawValue'); // Raw value to send 1052
var sendValue = ByteData(2);
sendValue.setUint16(0, rawValue.toInt(), Endian.little);
print('As Uint8List of values: ${sendValue.buffer.asUint8List()}');
// As Uint8List of values: [28, 4]
}
The dart:typed_data library has some useful methods to convert data to bytes. This method worked for me.
import 'dart:typed_data';
List<int> doubleToListInt(double value) {
ByteData bytes = ByteData(8);
bytes.setFloat64(0, value);
List<int> response =
bytes.buffer.asInt8List().toList();
return response;
}
print(doubleToListInt(10.52)); // Returns [64, 37, 10, 61, 112, -93, -41, 10]

Base64 string reduces after putting Map (data structure) into json.decode(map)

I am converting an Image to base64 and then I am putting it into the Map data structure, but when I convert Map into the JSON string, base64 string reduces and gets the reduced length response from the server. My question is why is Map reducing it?
"Message": "Invalid length for a Base-64 char array or string."
Converting Image file to Base64
var imageBytes = pfImage.readAsBytesSync();
String base64Image = base64Encode(imageBytes);
print("base64 is =$base64Image");
putting into the map
var petData = Map<String, dynamic>();
petData['user_id'] = 55;
petData['name'] = "sdf";
petData['breed'] = "dsf";
petData['StrImageBase64'] =base64Image != null ? base64Image : "";
converting to json string
print("map>>" + json.encode(map));
Some More Info
I have checked it locally as well by putting base64string into map and then print it, the result is in reduced string.
petData['StrImageBase64'] ="/9j/4AAQSkZJRgABAQAAAQABAAD/4RllRXhpZgAASUkqAAgAAAAHABoBBQABAAAAYgAAABsBBQABAAAAagAAACgBAwABAAAAAgAAADIBAgAUAAAAcgAAABMCAwABAAAAAQAAAGmHBAABAAAAhgAAACWIBAABAAAA6AAAACoBAABIAAAAAQAAAEgAAAABAAAAMjAxOToxMToxMCAwNTo1NTozMwAHAACQBwAEAAAAMDIxMAGRBwAEAAAAAQIDAAqSBQABAAAA4AAAAACgBwAEAAAAMDEwMAGgAwABAAAA//8AAAKgBAABAAAAAAUAAAOgBAABAAAAwAMAAAAAAAAkEwAA6AMAAAIABwAFAAMAAAAGAQAAHQACAAsAAAAeAQAAAAAAAAAAAAABAAAANwAAAAEAAAAfAAAAAQAAADIwMTk6MTE6MTAAAAIAAQIEAAEAAABIAQAAAgIEAAEAAAAVGAAAAAAAAP/Y/+AAEEpGSUYAAQEAAAEAAQAA/9sAQwAGBAUGBQQGBgUGBwcGCAoQCgoJCQoUDg8MEBcUGBgXFBYWGh0lHxobIxwWFiAsICMmJykqKRkfLTAtKDAlKCko/9sAQwEHBwcKCAoTCgoTKBoWGigoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo/8AAEQgA8AFAAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX2";
print("json.encode =${json.encode(petData)}");
UPDATED
It is not possible, that the map can reduce the value, or Json.decode(map) returns the reduced base64 string, Actually its VS code editor issue for not showing full base64 value.

Encoding a String in NetSuite SuiteScript 2.0

I have to perform the following encoding on a string:
Calculate SHA1 hash value, with output in hexadecimal format
Apply a BASE64 encoding to the resulted hash
I'm trying to do this in the code below, 'str' being the input and 'digest' the final encoded string.
I've tried different ways without much success. The current code (below) throws an error:
WrappedException: Wrapped java.lang.IllegalArgumentException: contains illegal character for hexBinary: crypto.SecretKey
var str = nonce + timestamp + secret;
var secureString = HTTPS.createSecureString({
input: str
});
secureString = secureString.hash({
algorithm: CRYPTO.HashAlg.SHA1
});
var hexString = HTTPS.createSecretKey({
encoding: HTTPS.Encoding.HEX,
guid: secureString
});
var digest = ENCODE.convert({
string: hexString,
inputEncoding: ENCODE.Encoding.HEX,
outputEncoding: ENCODE.Encoding.BASE_64
});

How do I convert a string into a vector of bytes in rust?

That might be the dumbest Rustlang question ever but I promise I tried my best to find the answer in the documentation or any other place on the web.
I can convert a string to a vector of bytes like this:
let bar = bytes!("some string");
Unfortunately I can't do it this way
let foo = "some string";
let bar = bytes!(foo);
Because bytes! expects a string literal.
But then, how do I get my foo converted into a vector of bytes?
(&str).as_bytes gives you a view of a string as a &[u8] byte slice (that can be called on String since that derefs to str, and there's also String.into_bytes will consume a String to give you a Vec<u8>.
Use the .as_bytes version if you don't need ownership of the bytes.
fn main() {
let string = "foo";
println!("{:?}", string.as_bytes()); // prints [102, 111, 111]
}
BTW, The naming conventions for conversion functions are helpful in situations like these, because they allow you to know approximately what name you might be looking for.
To expand the answers above. Here are a few different conversions between types.
&str to &[u8]:
let my_string: &str = "some string";
let my_bytes: &[u8] = my_string.as_bytes();
&str to Vec<u8>:
let my_string: &str = "some string";
let my_bytes: Vec<u8> = my_string.as_bytes().to_vec();
String to &[u8]:
let my_string: String = "some string".to_owned();
let my_bytes: &[u8] = my_string.as_bytes();
String to Vec<u8>:
let my_string: String = "some string".to_owned();
let my_bytes: Vec<u8> = my_string.into_bytes();
Specifying the variable type is optional in all cases. Just added to avoid confusion.
Playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=5ad228e45a38b4f097bbbba49100ecfc
`let v1: Vec<u8> = string.encode_to_vec();`
`let v2: &[u8] = string.as_bytes();`
two work difference, in some of library use ownership of bytes !! if you use as_bytes() see compiler error: must be static.
for example: tokio_uring::fs::File::write_at()
get a ownership of bytes !!
but if you need borrowing , use as_bytes()