Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decode base64URL to base64 -- Swift

Tags:

ios

swift

base64

I haven't found properly way how to decode base64URL to base64 format in swift.

According to base64url to base64 hJQWHABDBjoPHorYF5xghQ(base64URL) should be hJQWHABDBjoPHorYF5xghQ==(base64). Here could be more differences.

There are no solutions on stackoverflow.

like image 707
Anton Kashpor Avatar asked Apr 19 '17 15:04

Anton Kashpor


People also ask

How do I decode a Base64 encoded string in Swift?

Try this: let base64Encoded = "YW55IGNhcm5hbCBwbGVhc3VyZS4=" var decodedString = "" if let decodedData = Data(base64Encoded: base64Encoded) { decodedString = String(data: decodedData, encoding: . utf8)! }

What is Base64URL encoded?

Base64 encoding defines how to represent binary data in an ASCII string format. The objective of base64 encoding is to transmit binary data such as keys or digital certificates in a printable format.

What is Base64URL decode?

Base64URL Decode is a free online tool for decoding Base64URL values to original data. By default, it decodes Base64URL as plain text, nevertheless, it also supports binary data, such as images or other files.

Is BTOA a Base64?

The btoa() method creates a Base64-encoded ASCII string from a binary string (i.e., a string in which each character in the string is treated as a byte of binary data).


2 Answers

"base64url" differs from the standard Base64 encoding in two aspects:

  • different characters are used for index 62 and 63 (- and _ instead of + and /)
  • no mandatory padding with = characters to make the string length a multiple of four.

(compare https://en.wikipedia.org/wiki/Base64#Variants_summary_table).

Here is a possible conversion function:

func base64urlToBase64(base64url: String) -> String {
    var base64 = base64url
        .replacingOccurrences(of: "-", with: "+")
        .replacingOccurrences(of: "_", with: "/")
    if base64.characters.count % 4 != 0 {
        base64.append(String(repeating: "=", count: 4 - base64.characters.count % 4))
    }
    return base64
}

Example:

let base64url = "hJQWHABDBjoPHorYF5xghQ"
let base64 = base64urlToBase64(base64url: base64url)
print(base64) // hJQWHABDBjoPHorYF5xghQ==

if let data = Data(base64Encoded: base64) {
    print(data as NSData) // <8494161c 0043063a 0f1e8ad8 179c6085>
}

For the sake of completeness, this would be the opposite conversion:

func base64ToBase64url(base64: String) -> String {
    let base64url = base64
        .replacingOccurrences(of: "+", with: "-")
        .replacingOccurrences(of: "/", with: "_")
        .replacingOccurrences(of: "=", with: "")
    return base64url
}

Update for Swift 4:

func base64urlToBase64(base64url: String) -> String {
    var base64 = base64url
        .replacingOccurrences(of: "-", with: "+")
        .replacingOccurrences(of: "_", with: "/")
    if base64.count % 4 != 0 {
        base64.append(String(repeating: "=", count: 4 - base64.count % 4))
    }
    return base64
}
like image 88
Martin R Avatar answered Sep 29 '22 20:09

Martin R


Here is a cleaned up version of what Martin posted within a Swift 4 extension:

import Foundation

/// Extension for making base64 representations of `Data` safe for
/// transmitting via URL query parameters
extension Data {

    /// Instantiates data by decoding a base64url string into base64
    ///
    /// - Parameter string: A base64url encoded string
    init?(base64URLEncoded string: String) {
        self.init(base64Encoded: string.toggleBase64URLSafe(on: false))
    }

    /// Encodes the string into a base64url safe representation
    ///
    /// - Returns: A string that is base64 encoded but made safe for passing
    ///            in as a query parameter into a URL string
    func base64URLEncodedString() -> String {
        return self.base64EncodedString().toggleBase64URLSafe(on: true)
    }

}

extension String {

    /// Encodes or decodes into a base64url safe representation
    ///
    /// - Parameter on: Whether or not the string should be made safe for URL strings
    /// - Returns: if `on`, then a base64url string; if `off` then a base64 string
    func toggleBase64URLSafe(on: Bool) -> String {
        if on {
            // Make base64 string safe for passing into URL query params
            let base64url = self.replacingOccurrences(of: "/", with: "_")
                .replacingOccurrences(of: "+", with: "-")
                .replacingOccurrences(of: "=", with: "")
            return base64url
        } else {
            // Return to base64 encoding
            var base64 = self.replacingOccurrences(of: "_", with: "/")
                .replacingOccurrences(of: "-", with: "+")
            // Add any necessary padding with `=`
            if base64.count % 4 != 0 {
                base64.append(String(repeating: "=", count: 4 - base64.count % 4))
            }
            return base64
        }
    }

}
like image 31
iwasrobbed Avatar answered Sep 29 '22 21:09

iwasrobbed