1

Is there a way to convert a hexadecimal string to base64 in Swift? For example, I would like to convert:

BA5E64C0DE

to:

ul5kwN4=

It's possible to convert a normal string to base64 by using:

let hex: String = "BA5E64C0DE"

let utf8str: NSData = hex.dataUsingEncoding(NSUTF8StringEncoding)!
let base64Encoded: NSString = utf8str.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))

let base64: String = (base64Encoded as String)

But this would give a result of:

QkE1RTY0QzBERQ==

Because it's just treating the hex as a normal UTF-8 String, and not hexadecimal.

It's possible to convert it to base64 correctly by looping through every six hex characters and converting it to it's four respective base64 characters, but this would be highly inefficient, and is just plain stupid (there would need to be 17,830,160 if statements):

if(hex == "000000"){base64+="AAAA"}
else if(hex == "000001"){base64+="AAAB"}
else if(hex == "000002"){base64+="AAAC"}
else if(hex == "BA5E64"){base64+="ul5k"}
//...

It would be nice if there was something like this:

let hex: String = "BA5E64C0DE"

let data: NSData = hex.dataUsingEncoding(NSHexadecimalEncoding)!
let base64Encoded: NSString = data.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))

let base64: String = (base64Encoded as String)

But sadly, there's no NSHexadecimalEncoding. Is there any efficient way to convert a hexadecimal string to it's base64 representation in Swift?

Jojodmo
  • 23,357
  • 13
  • 65
  • 107
  • 2
    I've seen this down-vote pattern before (rapid downvote of question and all answers rapidly, but without a single explanation why) and it's quite tiresome. Perhaps they thought this was all duplicative of other discussions (though I think it's slightly different, even though it touches on issues well-covered elsewhere). I dunno. Did I answer your question, though? – Rob Apr 13 '15 at 04:49

2 Answers2

5

The base-64 string, "ul5kwN4=", translates to a binary NSData consisting of of five bytes BA, 5E, 64, C0, and DE.

Now, if you really had a string with the hexadecimal representation, you could convert it to a binary NSData using a routine like the one here: https://stackoverflow.com/a/26502285/1271826

Once you have a NSData, you could build your base 64 string:

let hexString = "BA5E64C0DE"
let binaryData = hexString.dataFromHexadecimalString()
let base64String = binaryData?.base64EncodedStringWithOptions(nil)

That generates the desired output, ul5kwN4=.

Community
  • 1
  • 1
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • @Jojodmo I notice you changed your example. I changed my implementation and confirmed I'm getting the desired base64 string. – Rob Apr 13 '15 at 15:19
  • 1
    Thanks, I was able to get it to work. May I suggest adding the full code to this answer instead of linking to another answer? ([here's the code I used](http://i.gyazo.com/8dfb1222de9ed0688b4e395bf113b6f1.png)) – Jojodmo Apr 14 '15 at 02:47
  • is it possible to convert base 64 to hexadecimal string – Kiran P Nair Dec 12 '16 at 15:11
  • @BraneDullet - Just reverse the process, creating a `Data`/`NSData` from the string (https://developer.apple.com/reference/foundation/nsdata/1410081-init) and then, if you really need a hexadecimal string representation of that, use the `hexadecimal()` method in [that other answer](http://stackoverflow.com/a/26502285/1271826). – Rob Dec 12 '16 at 17:43
  • @Rob, what is swift 3 alternative? – Chanchal Raj Jan 05 '17 at 12:20
  • 1
    @ChanchalRaj - The Swift 3 rendition is at the end of the linked Stack Overflow question. – Rob Jan 05 '17 at 15:53
2
  1. First, convert Hex String to Data using the following routine. (Worked in Swift 3.0.2)

    extension String {
        /// Expanded encoding
        ///
        /// - bytesHexLiteral: Hex string of bytes
        /// - base64: Base64 string
        enum ExpandedEncoding {
            /// Hex string of bytes
            case bytesHexLiteral
            /// Base64 string
            case base64
        }
    
        /// Convert to `Data` with expanded encoding
        ///
        /// - Parameter encoding: Expanded encoding
        /// - Returns: data
        func data(using encoding: ExpandedEncoding) -> Data? {
            switch encoding {
            case .bytesHexLiteral:
                guard self.characters.count % 2 == 0 else { return nil }
                var data = Data()
                var byteLiteral = ""
                for (index, character) in self.characters.enumerated() {
                    if index % 2 == 0 {
                        byteLiteral = String(character)
                    } else {
                        byteLiteral.append(character)
                        guard let byte = UInt8(byteLiteral, radix: 16) else { return nil }
                        data.append(byte)
                    }
                }
                return data
            case .base64:
                return Data(base64Encoded: self)
            }
        }
    }
    
  2. Then, convert Data to Base64 String using Data.base64EncodedString(options:).


Usage

let base64 = "BA5E64C0DE".data(using: .bytesHexLiteral)?.base64EncodedString()
if let base64 = base64 {
    print(base64)
    // Prints "ul5kwN4="
}
jqgsninimo
  • 6,562
  • 1
  • 36
  • 30