How to encode and decode Base64 and Base64Url in Flutter / Dart - dart

I want to encode the following string in Base64Url in Flutter and decode it in on a Dart server.
"username:password"
How do I do that? And how do I do it in Base64?

The dart:convert library contains an encoder and decoder for Base64 and Base64Url. However, they encode and decode Lists of integers, so for strings you also need to encode and decode in UTF-8. Rather than doing these two encodings separately, you can combine them with fuse.
You need to have the following import:
import 'dart:convert';
Base64
String credentials = "username:password";
Codec<String, String> stringToBase64 = utf8.fuse(base64);
String encoded = stringToBase64.encode(credentials); // dXNlcm5hbWU6cGFzc3dvcmQ=
String decoded = stringToBase64.decode(encoded); // username:password
Note that this is equivalent to:
String encoded = base64.encode(utf8.encode(credentials)); // dXNlcm5hbWU6cGFzc3dvcmQ=
String decoded = utf8.decode(base64.decode(encoded)); // username:password
Base64Url
String credentials = "username:password";
Codec<String, String> stringToBase64Url = utf8.fuse(base64Url);
String encoded = stringToBase64Url.encode(credentials); // dXNlcm5hbWU6cGFzc3dvcmQ=
String decoded = stringToBase64Url.decode(encoded); // username:password
Again, this is equivalent to:
String encoded = base64Url.encode(utf8.encode(credentials)); // dXNlcm5hbWU6cGFzc3dvcmQ=
String decoded = utf8.decode(base64Url.decode(encoded)); // username:password
See also
RCF 4648
String based data encoding: Base64 vs Base64url

Related

Swift String and base64Encode Confusion

I have problem with encoding data. My token has 1228 characters and
let data = Data(base64Encoded: tokenString)!
works fine, but when i add to token some information and my token has 1263 characters Data(base64Encoded:) returns nil.
Problem in my opinion is in the string length or Data(base64Encoded:).
Does Data(base64Encoded:) have any restrictions on the length of characters?
Please give me some info about this problem.
Not sure how you encode the modified token, but looks like the encoded Base64 string doesn't include padding characters. Appending = to the modified token seems to fix the decoding issue:
// original token -> 57 bytes
let data1 = Data(base64Encoded: "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyMTF9")
// modified token -> nil
let data2 = Data(base64Encoded: "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyMX0")
// modified token with '=' for padding -> 56 bytes
let data2Fixed = Data(base64Encoded: "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyMX0=")
// decodes correctly: "{"sub":"1234567890","name":"John Doe","iat":15162390221}"
let string = String(data: data2Fixed!, encoding: .utf8)
So to solve it properly you probably need to look into the encoder. Hope that helps!

Swift URL.path changes encoding of utf-8 characters

Why does converting a String to an URL in Swift 4.2 and then converting the URL back to a String using url.path change the encoding of special characters like german umlauts (ä, ö, ü), even if I use a utf-8 encoding?
I wrote some sample code to show my problem. I encoded the strings to base64 in order to show that there is a difference.
I also have a similar unsolved problem with special characters and swift here.
Sample Code
let string = "/path/to/file"
let stringUmlauts = "/path/to/file/with/umlauts/testäöü"
let base64 = Data(string.utf8).base64EncodedString()
let base64Umlauts = Data(stringUmlauts.utf8).base64EncodedString()
print(base64, base64Umlauts)
let url = URL(fileURLWithPath: string)
let urlUmlauts = URL(fileURLWithPath: stringUmlauts)
let base64Url = Data(url.path.utf8).base64EncodedString()
let base64UrlUmlauts = Data(urlUmlauts.path.utf8).base64EncodedString()
print(base64Url, base64UrlUmlauts)
Output
The base64 and base64Url string stay the same but the base64Umlauts and the base64UrlUmlauts are different.
"L3BhdGgvdG8vZmlsZQ==" for base64
"L3BhdGgvdG8vZmlsZQ==" for base64Url
"L3BhdGgvdG8vZmlsZS93aXRoL3VtbGF1dHMvdGVzdMOkw7bDvA==" for base64Umlauts
"L3BhdGgvdG8vZmlsZS93aXRoL3VtbGF1dHMvdGVzdGHMiG/MiHXMiA==" for base64UrlUmlauts
When I put the base64Umlauts and base64UrlUmlauts strings into an online Base64 decoder, they both show /path/to/file/with/umlauts/testäöü, but the ä, ö, ü are different (not visually).
stringUmlauts.utf8 uses the Unicode characters äöü.
But urlUmlauts.path.utf8 uses the Unicode characters aou each followed by the combining ¨.
This is why you get different base64 encoding - the characters look the same but are actually encoded differently.
What's really interesting is that Array(stringUmlauts) and Array(urlUmlauts.path) are the same. The difference doesn't appear until you perform the UTF-8 encoding of the otherwise exact same String values.
Since the base64 encoding is irrelevant, here's a more concise test:
let stringUmlauts = "/path/to/file/with/umlauts/testäöü"
let urlUmlauts = URL(fileURLWithPath: stringUmlauts)
print(stringUmlauts, urlUmlauts.path) // Show the same
let rawStr = stringUmlauts
let urlStr = urlUmlauts.path
print(rawStr == urlStr) // true
print(Array(rawStr) == Array(urlStr)) // true
print(Array(rawStr.utf8) == Array(urlStr.utf8)) // false!!!
So how is the UTF-8 encoding of two equal strings different?
One solution to this is to use precomposedStringWithCanonicalMapping on the result of path.
let urlStr = urlUmlauts.path.precomposedStringWithCanonicalMapping
Now you get true from:
print(Array(rawStr.utf8) == Array(urlStr.utf8)) // now true

How to identify UTF-8 encoded text from a string and convert it to smiley\emoticon in Swift

I am doing App which support Smiley/emoticons feature. From the backend I am getting response like this str = "Hferuhggeðððððfjjnjrnjgnejfnsgjen".
This string response has a UTF-8 encoded text in it, for the above str UTF-8 encode text is "ððððð".
Now I need to identify the location of the utf-8 encoded text from the response obtained, and convert that encoded text to an emoticon/smiley.
Finally I found solution if you decode string you will get smiley ,please find the code
let che = descriptionText.cString(using: .isoLatin1)
let decode_string = String(cString: che!, encoding: .utf8)
This worked for me.

RFC2045-MIME variant of Base 64 in swift

I need to convert a encode a string with the RFC2045-MIME variant of base64. However I cant find any options to do this in swift. At the moment i use this method:
var str = "\(test1):\(test2)"
str = str.data(using: .utf8)!.base64EncodedString(options: Data.Base64EncodingOptions(rawValue: UInt(0)))
but this is just the standard base64 encoding not the RFC2045-MIME variant. How can i use the RFC2045-MIME variant?
The only differences between the base64 encodings specified in RFC 2045 and RFC 4686 are that RFC 2045 specifies a maximum line length of 76 characters, with lines separated by CRNL.
The documentation of base64EncodedString(options:) says the default line ending is CRNL, so:
let data = str.data(using: .utf8)!
let b64 = data.base64EncodedString(options: .lineLength76Characters)

Decode Data that is base64String to String utf Swift

A library save a token as Data in UserDefaults
//loading the token
if let token = UserDefaults.standard.object(forKey: "token") as? Data {
let base64Encoded = token.base64EncodedData
let base64EncodedString = token.base64EncodedString()
}
When I print that base64Encoded value in the console I get the value: Y2E2N2Y5NTItNDVkOC00YzZkLWFkZDMtZGRiMjc5NGE3YWI2OjdmZDU1ZTAyLWExMjEtNGQ1ZC05N2MzLWM5OWY4NTg5NTIzNg== as Data
When I copy this value from the output in the console and use this website https://www.base64decode.org/ I got the expected result. ca67f952-45d8-4c6d-add3-ddb2794a7ab6:7fd55e02-a121-4d5d-97c3-c99f85895236
My problem is that I don't get convert that base64Encoded to String in my code.
When I use base64EncodedString I got a string, but I can't figure out which format this is: PFsYdirs21247rRG/XcWOVGUGUcCCTzXz7VFAnunLJU= The method base64EncodedString() This is an method from Apple: https://developer.apple.com/documentation/foundation/nsdata/1413546-base64encodedstring
When I decode this value to utf8 at the website I got: <[v*]Fw9QG
When I try to convert my base64Encoded (Data, not String) to a string like this
if let toString = String(data: base64Encoded, encoding: String.Encoding.utf8) as String {
print("test \(toString)")
}
my compiler threw an error: Cannot convert value of type(Data.Base64EncodingOptions) -> Data to expected argument type Data
Here I found a solution to decode when my Data-value would be a string.
https://stackoverflow.com/a/31859383/4420355
So I'm quite confused about the results. Long story short:
I have base64Encoded Data (Y2E2N2Y5NTItNDVkOC00YzZkLWFkZDMtZGRiMjc5NGE3YWI2OjdmZDU1ZTAyLWExMjEtNGQ1ZC05N2MzLWM5OWY4NTg5NTIzNg==) and want them convert to an utf8 string. I don't get handle this.

Resources