How to convert a base64String to String in Swift?
Try this:
let base64Encoded = "YW55IGNhcm5hbCBwbGVhc3VyZS4="
var decodedString = ""
if let decodedData = Data(base64Encoded: base64Encoded) {
decodedString = String(data: decodedData, encoding: .utf8)!
}
if !decodedString.isEmpty {
print(decodedString)
} else {
print("Oops, invalid input format!")
}
Make sure your base 64 encoded string is valid.
WARNING (edit)
In most base64
decoding implementations like Java
, the padding-character is not needed, but Data(base64Encoded:)
returns nil
if it's missing.
Swift 5 solution; use String.fromBase64(_:)
instead, after implementing like:
extension Data {
/// Same as ``Data(base64Encoded:)``, but adds padding automatically
/// (if missing, instead of returning `nil`).
public static func fromBase64(_ encoded: String) -> Data? {
// Prefixes padding-character(s) (if needed).
var encoded = encoded;
let remainder = encoded.count % 4
if remainder > 0 {
encoded = encoded.padding(
toLength: encoded.count + 4 - remainder,
withPad: "=", startingAt: 0);
}
// Finally, decode.
return Data(base64Encoded: encoded);
}
}
extension String {
public static func fromBase64(_ encoded: String) -> String? {
if let data = Data.fromBase64(encoded) {
return String(data: data, encoding: .utf8)
}
return nil;
}
}
As mentioned on editor's profile,
above edit's code allows Apache 2.0 license as well,
without attribution need.
Decode base64 string in Swift
Your string is missing the =
padding characters at the end of a base64 output to make the string length divisible by 4. Try with
eyJhbGciOiJSUzI1NiIsImtpZCI6IjdEODU3RjE3RjMwQTBBNzY4OUQ4RTFDMTI0RjRFMzk1MEU2REIyQ0YiLCJ0eXAiOiJKV1QiLCJ4NXQiOiJmWVZfRl9NS0NuYUoyT0hCSlBUamxRNXRzczgifQ==
Decoding Base64 String Returns nil
Your string contains underscore character ('_' U+005F LOW LINE), which is invalid as Base-64.
There are some variations of Base-64, so you need to find which one your Gmail something is using. (Wikipedia Base-64.)
Assuming it uses base64url URL- and filename-safe, you may need to write something like this:
extension String {
func urlSafeBase64Decoded() -> String? {
var st = self
.replacingOccurrences(of: "_", with: "/")
.replacingOccurrences(of: "-", with: "+")
let remainder = self.count % 4
if remainder > 0 {
st = self.padding(toLength: self.count + 4 - remainder,
withPad: "=",
startingAt: 0)
}
guard let d = Data(base64Encoded: st, options: .ignoreUnknownCharacters) else{
return nil
}
return String(data: d, encoding: .utf8)
}
}
Example:
let base64 = "WW91ciBhY2NvdW50IHNhbG1hbm1hamlkMTRAZ21haWwuY29tIGlzIGxpc3RlZCBhcyB0aGUgcmVjb3ZlcnkgZW1haWwgZm9yDQpzaWRyYWlicmFoaW0wMzQ5QGdtYWlsLmNvbS4gRG9uJ3QgcmVjb2duaXplIHRoaXMgYWNjb3VudD8gQ2xpY2sgaGVyZQ0KPGh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9BY2NvdW50RGlzYXZvdz9hZHQ9QU9YOGtpcHBKRG5OX19KVGloejdoUHRnMlFwRHRRb3VETWVUalRMN2J4YjA3b2dJRC1xYm54QnZPRElTUjB3Q1h6RHlYQSZyZm49MTI3JmFuZXhwPWdpdmFiLWZhLS1tZHYyLWZhPg0KR29vZ2xlIEFQSXMgRXhwbG9yZXIgd2FzIGdyYW50ZWQgYWNjZXNzIHRvIHlvdXIgbGlua2VkIEdvb2dsZSBBY2NvdW50DQoNCg0Kc2lkcmFpYnJhaGltMDM0OUBnbWFpbC5jb20NCg0KSWYgeW91IGRpZCBub3QgZ3JhbnQgYWNjZXNzLCB5b3Ugc2hvdWxkIGNoZWNrIHRoaXMgYWN0aXZpdHkgYW5kIHNlY3VyZSB5b3VyDQphY2NvdW50Lg0KQ2hlY2sgYWN0aXZpdHkNCjxodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20vQWNjb3VudENob29zZXI_RW1haWw9c2lkcmFpYnJhaGltMDM0OUBnbWFpbC5jb20mY29udGludWU9aHR0cHM6Ly9teWFjY291bnQuZ29vZ2xlLmNvbS9hbGVydC9udC8xNTY3ODQ3ODEyMDAwP3JmbiUzRDEyNyUyNnJmbmMlM0QxJTI2ZWlkJTNELTE1NzQzMDEyNjk4Mjg2MTM3OTQlMjZldCUzRDElMjZhbmV4cCUzRGdpdmFiLWZhLS1tZHYyLWZhPg0KWW91IHJlY2VpdmVkIHRoaXMgZW1haWwgdG8gbGV0IHlvdSBrbm93IGFib3V0IGltcG9ydGFudCBjaGFuZ2VzIHRvIHlvdXINCkdvb2dsZSBBY2NvdW50IGFuZCBzZXJ2aWNlcy4NCsKpIDIwMTkgR29vZ2xlIExMQywgMTYwMCBBbXBoaXRoZWF0cmUgUGFya3dheSwgTW91bnRhaW4gVmlldywgQ0EgOTQwNDMsIFVTQQ0K"
print(base64.urlSafeBase64Decoded() ?? "* decoding failed*")
Output:
You received this email to let you know about important changes to your
Google Account and services.
© 2019 Google LLC, 1600 Amphitheatre Parkway, Mountain View, CA 94043, USA
Convert base64-encoded string to normal string in swift 3
Looking at your revised question, you're trying to take this base-64 string, and using it as the iv
in your AES algorithm. I can understand why you are wondering how to convert that resulting Data
into a String
, but you should not do that. Yes, there's a rendition of AES
that expects the iv
as a string. But there's another rendition that expects an Array<UInt8>
. So, just like MartinR said in his answer to your other question, build an array of UInt8
instead, like so:
let iv = Array(Data(base64Encoded: "dfYcSGpvBqyzvkAXkdbHDA==")!)
That resulting iv
is an Array<UInt8>
(also known as [UInt8]
). You can use that with your AES
function.
My original discussion about converting Data
objects to UTF8 strings is below. But the key message is that you shouldn't try to do so. Just build your array of UInt8
and use that with your library's AES
function.
Looking at your other question (Convert hex-encoded String to String in Swift 3), you revealed in comments that you were dealing with an AES key. I'm suspicious that we're dealing with a similar issue here (though that was 32 bytes of data, and here we have 16 bytes).
Bottom line, I'd suggest you completely drop this "how to I get a string representation of the data captured in this base-64 string" line of inquiry. If it's an encryption key (or some token or whatever), don't bother trying to represent it as a string. (This is the raison d'être of base-64, to create transmittable string representations of data that isn't a string.)
I'd suggest you step back and describe the broader problem that you are trying to solve. Stop trying to create strings out of these binary payloads. In your code snippet, you successfully create a Data
from the base-64 string. The real question, I think, is not "how do I now get a string from that?", but rather "what do I do this Data
?"
We can't answer that question without more context about where you got this data and what it is for.
By the way, my original answer to your question is below.
The problem is that base-64 string translates to 16 bytes of data whose hexadecimal representation is
75f61c48 6a6f06ac b3be4017 91d6c70c
But that payload is not valid UTF8 string. The third byte, 1c
is not consistent with UTF8 string. If you look at the definition of UTF8, it says that if a byte is in the range of f6
–fb
, which the second byte is, that the character consists of that and the following two bytes, both of which should be in the range of 21
–7e
or a0
–ff
, which 1c
is not.
So, this simply is not a valid UTF8 string. Clearly those sites you're using are not gracefully detecting/handling invalid UTF8 strings.
Perhaps the data in this base-64 string was converted from a string using a different encoding. Or, perhaps it was not originally a string at all. Not all binary payloads have clean string representations. Frankly, this is why we use base-64 representations in the first place, to come up with a text representation of a blob of data that is not a string.
If you provide more information about the source of the data contained in this base-64 string, we might be able to advise you further.
How can I encode a string to Base64 in Swift?
I don’t have 6.2 installed but I don’t think 6.3 is any different in this regard:
dataUsingEncoding
returns an optional, so you need to unwrap that.
NSDataBase64EncodingOptions.fromRaw
has been replaced with NSDataBase64EncodingOptions(rawValue:)
. Slightly surprisingly, this is not a failable initializer so you don’t need to unwrap it.
But since NSData(base64EncodedString:)
is a failable initializer, you need to unwrap that.
Btw, all these changes were suggested by Xcode migrator (click the error message in the gutter and it has a “fix-it” suggestion).
Final code, rewritten to avoid force-unwraps, looks like this:
import Foundation
let str = "iOS Developer Tips encoded in Base64"
println("Original: \(str)")
let utf8str = str.dataUsingEncoding(NSUTF8StringEncoding)
if let base64Encoded = utf8str?.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
{
println("Encoded: \(base64Encoded)")
if let base64Decoded = NSData(base64EncodedString: base64Encoded, options: NSDataBase64DecodingOptions(rawValue: 0))
.map({ NSString(data: $0, encoding: NSUTF8StringEncoding) })
{
// Convert back to a string
println("Decoded: \(base64Decoded)")
}
}
(if using Swift 1.2 you could use multiple if-lets instead of the map)
Swift 5 Update:
import Foundation
let str = "iOS Developer Tips encoded in Base64"
print("Original: \(str)")
let utf8str = str.data(using: .utf8)
if let base64Encoded = utf8str?.base64EncodedString(options: Data.Base64EncodingOptions(rawValue: 0)) {
print("Encoded: \(base64Encoded)")
if let base64Decoded = Data(base64Encoded: base64Encoded, options: Data.Base64DecodingOptions(rawValue: 0))
.map({ String(data: $0, encoding: .utf8) }) {
// Convert back to a string
print("Decoded: \(base64Decoded ?? "")")
}
}
Related Topics
Why Can't I Pass a Protocol.Type to a Generic T.Type Parameter
Calculate Age from Birth Date Using Nsdatecomponents in Swift
Swift - Iboutletcollection Equivalent
Checking If an Object Is a Given Type in Swift
How to Detect If an Skspritenode Has Been Touched
How to Create a Segue That Can Be Called from a Button That Is Created Programmatically
Programmatically Detect Tab Bar or Tabview Height in Swiftui
Forced to Cast, Even If Protocol Requires Given Type
Why Are Emoji Characters Like 👩👩👧👦 Treated So Strangely in Swift Strings
How to Set Layer Cornerradius For Only Bottom-Left, Bottom-Right, and Top-Left Corner
Get a Swift Variable'S Actual Name as String
How to Find String B Missing Characters Based on String a and Add Them to String B
Express For Loops in Swift With Dynamic Range
Swift Random Float Between 0 and 1
How to Display an Activity Indicator With Text on iOS 8 With Swift
Iterate Through Files in a Folder and Its Subfolders Using Swift'S Filemanager