Swift Base64 Decoding Returns Nil

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

Decoding base64String value returns nil

You can try this code:

let decodedData = NSData(base64EncodedString: base64String, options:NSDataBase64DecodingOptions.IgnoreUnknownCharacters)

Swift 2 Decode base64 always return nil

I doubt on string "PY5ehymWfQKExWxPyOImGiQkxNjyuBREmOXtQdePVpuH9PFzizaO+WTuM1sLouTQPz5UO7csloC9GjOFqkq4POmlB9d3mMJGLB2pVCNs8t9EejOcjV4fRHaITkmfMfVbizCnTvHGBwLWXjLc7gwyhu2+S9qw0NXc5jw6EdEk+zuesrdwLgqws0hDqFSoVw57+CnvUmgXwtNfKP4p64mJ9inH/0xAMarCc5N4Wjz/zmlTyd2PoDFUC/iLdZ7csau7X2M="

This works, that string getting encode and decode too

    let utf8str = "PY5ehymWfQKExWxPyOImGiQkxNjyuBREmOXtQdePVpuH9PFzizaO+WTuM1sLouTQPz5UO7csloC9GjOFqkq4POmlB9d3mMJGLB2pVCNs8t9EejOcjV4fRHaITkmfMfVbizCnTvHGBwLWXjLc7gwyhu2+S9qw0NXc5jw6EdEk+zuesrdwLgqws0hDqFSoVw57+CnvUmgXwtNfKP4p64mJ9inH/0xAMarCc5N4Wjz/zmlTyd2PoDFUC/iLdZ7csau7X2M=".dataUsingEncoding(NSUTF8StringEncoding)
let base64Encoded = utf8str?.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
let encodedString : String = base64Encoded!
print(encodedString) // my encoded data

let decodedData = NSData(base64EncodedString: encodedString, options:NSDataBase64DecodingOptions(rawValue: 0))
let decodedString : String = String(data: decodedData!, encoding: NSUTF8StringEncoding)!
print(decodedString) // my plain data

This doesn't work, that decoded string dont get encode

    let decodedData = NSData(base64EncodedString:  "PY5ehymWfQKExWxPyOImGiQkxNjyuBREmOXtQdePVpuH9PFzizaO+WTuM1sLouTQPz5UO7csloC9GjOFqkq4POmlB9d3mMJGLB2pVCNs8t9EejOcjV4fRHaITkmfMfVbizCnTvHGBwLWXjLc7gwyhu2+S9qw0NXc5jw6EdEk+zuesrdwLgqws0hDqFSoVw57+CnvUmgXwtNfKP4p64mJ9inH/0xAMarCc5N4Wjz/zmlTyd2PoDFUC/iLdZ7csau7X2M=", options:NSDataBase64DecodingOptions(rawValue: 0))
let decodedString : String = String(data: decodedData!, encoding: NSUTF8StringEncoding)!
print(decodedString) // my plain data

This could be reason, check on https://www.base64decode.org/

Sample Image

Though special characters can't be hold in String.

Swift NSData from base64encoded string returns nil

Try to use IgnoreUnknownCharacters option.

Or try to use initWithBase64EncodedString from NSDataAdditions

base64encoded string returned from API call is showing nil after Data(base64encoded: data) is ran

You need to check your data length, divide by 3 and in case the result is not zero add one or two bytes (65) = equal sign for padding your data. Try like this:

let decodedData = Data(base64Encoded: data + .init(repeating: 65, count: data.count % 3))

extension Data {
var base64encodedDataPadded: Data {
let data = last == 46 ? dropLast() : self
return data + .init(repeating: 65, count: data.count % 3)
}
}

Playground testing:

let data = Data("eyJzdWNjZXNzIjoiZmFsc2UiLCJlcnJvciI6Im1vYmlsZV9waW5fY29ubmVjdDogaW52YWxpZCBvciBleHBpcmVkIn0.".utf8)
let decodedData = Data(base64Encoded: data.base64encodedDataPadded)!
print(String(data: decodedData, encoding: .utf8)!) // "{"success":"false","error":"mobile_pin_connect: invalid or expired"}"

Can not use base64 decode in swift

The problem with your base64 encoded string is that it is not properly terminated. You just need to add "==" to the end of your string:

let base64Code = "eyJyb2xlcyI6WyJVc2VyIiwiTWFpbnRhaW5lciJdLCJhdWQiOiJzdHVkZW50cyIsImV4cCI6MTYwMTk5MjU5OCwiaWF0IjoxNjAxOTg4OTk4LCJpc3MiOiJzZXJ2aWNlIHByb2plY3QiLCJzdWIiOiI0NWI1ZmJkMy03NTVmLTQzNzktOGYwNy1hNThkNGEzMGZhMmYifQ"

let base64CodeCount = base64Code.count
let decodedData = Data(base64Encoded: base64Code + repeatElement("=", count: base64CodeCount.isMultiple(of: 4) ? 0 : 4 - base64CodeCount % 4))!
let json = String(data: decodedData, encoding: .utf8)! // "{"roles":["User","Maintainer"],"aud":"students","exp":1601992598,"iat":1601988998,"iss":"service project","sub":"45b5fbd3-755f-4379-8f07-a58d4a30fa2f"}"

Can't decode base64 encoded string

Your issue is two-fold.

The trivial part is that you are force-unwrapping an optional return type, which can easily be resolved by if let or nil coalescing.

The other part is that the encoded data is not actually a .utf8 string. It seems to be .ascii

If not knowing the actual string encoding is a problem you will regularly face, it might be worth extending the extension (!) to accommodate this.

extension String {
func base64Decoded() -> (String, String.Encoding)? {
let supportedEncoding: [String.Encoding] = [.ascii, .utf8, .utf16] //etc.
guard let data = Data(base64Encoded: self),
let encoding = supportedEncoding.first(where: {String(data: data, encoding: $0) != nil})
else {return nil}
return (String(data: data, encoding: encoding)!, encoding)
}
}

The method now also return the encoding type. If this isn't useful, revert to just returning the optional String.

Unfortunately String.Encoding is a struct with many static values rather than an enum, which means it's necessary to define the various encodings values. If it was an enum it would be simple to iterate over the .allcases values.



Related Topics



Leave a reply



Submit