0

I have the following base64 encoded string and I need to base64 decode it using Swift:

KimHser2RvFf9RPjajWO4K/odT51hTlISwMKNIfPUC+gXYZKNjGDCvHEom++6liXNq6PkStnpzMKBsTk+tIpJA==

There is no line break there, StackOverflow is just wrapping the string. I have tried numerous methods to base64 decode this. I do receive a result as NSData, however, when I try to convert the NSData to an NSString object, the result is always nil. If I change the encoding to ASCII or UTF16 I receive a result, so I assume Swift is not recognizing the NSData in UTF8 format. However, if I base 64 decode the same string in C#, UTF8 works, and the Base64 decoding works. So I'm positive I'm missing a step due to my lack of experience with Swift.

Here is my latest attempt:

import Foundation

extension String {
// MARK: Base64 encode
func base64Encode() -> String {
    let data : NSData = self.dataUsingEncoding(NSUTF8StringEncoding)!
    return data.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
}

// MARK: Base64 decode
func base64Decode() -> String {
    let decodedData = NSData(base64EncodedString: self, options: NSDataBase64DecodingOptions(rawValue: 0))
    let decodedString = NSString(data: decodedData!, encoding: NSUTF8StringEncoding)
    return decodedString as! String
}
}

I'm positive it's something easy. However, this is my first application in Swift and I'm still learning.

Any help is much appreciated.

Thanks!

4
  • 1
    decodedData is <2a2987b1 ... fad22924> which is definitely not a valid UTF-8 sequence. What result do you expect? Commented Nov 4, 2015 at 21:31
  • I'm trying to implement the Azure Shared Access Signature to query my Azure Storage Service from iOS. This is the access key they give me (don't worry, I already reset my keys). However, none of them work in Swift when trying to base64 decode into an NSString so I can use the decode string as the key to HMACSHA256 to generate the Shared Access Signature. Commented Nov 5, 2015 at 13:06
  • I don't know anything about Azure and the details of the Azure signature algorithm. But I strongly assume that you can use the data directly as the key to HMACSHA256, instead of converting it to a string first. Commented Nov 5, 2015 at 13:16
  • Thanks Martin. All of the examples I have found so far use a String, but I'll investigate options just using NSData. Commented Nov 5, 2015 at 13:19

2 Answers 2

1

Your "base64" string is invalid. If you try to decode it in some online decoder it fails. But your code is valid :)
Correction
If original data that was encoded isn't a string data then I agree with @Martin R

Sign up to request clarification or add additional context in comments.

2 Comments

The Base64 string is valid. It decodes to binary data which cannot be represented as NSString. The online decoder most probably fails because it also assumes that the decoded data represents a string in some encoding (UTF-8 or ISO Latin or ...)
Unfortunately, I do not make that base64 string. It's coming from another system. Is there a way in Swift I can decode it to a NSString? Eventually my goal is to take this base64 encoded string, decode it, then use the decode value as a HMACSHA256 key. It's all part of authenticating with the Microsoft Azure Storage Service REST API.
-1

Just in case anyone other newbies need to hit the Azure Storage Service through REST and iOS Swift, below is the code that worked for me. I used String extensions here only until I could figure it out. This will end up in its own class.

    import Foundation

enum HMACAlgorithm {
    case MD5, SHA1, SHA224, SHA256, SHA384, SHA512

    func toCCHmacAlgorithm() -> CCHmacAlgorithm {
        var result: Int = 0
        switch self {
        case .MD5:
            result = kCCHmacAlgMD5
        case .SHA1:
            result = kCCHmacAlgSHA1
        case .SHA224:
            result = kCCHmacAlgSHA224
        case .SHA256:
            result = kCCHmacAlgSHA256
        case .SHA384:
            result = kCCHmacAlgSHA384
        case .SHA512:
            result = kCCHmacAlgSHA512
        }
        return CCHmacAlgorithm(result)
    }

    func digestLength() -> Int {
        var result: CInt = 0
        switch self {
        case .MD5:
            result = CC_MD5_DIGEST_LENGTH
        case .SHA1:
            result = CC_SHA1_DIGEST_LENGTH
        case .SHA224:
            result = CC_SHA224_DIGEST_LENGTH
        case .SHA256:
            result = CC_SHA256_DIGEST_LENGTH
        case .SHA384:
            result = CC_SHA384_DIGEST_LENGTH
        case .SHA512:
            result = CC_SHA512_DIGEST_LENGTH
        }
        return Int(result)
    }
}

extension String {

    func hmac(algorithm: HMACAlgorithm, key: String) -> String {
        let cKey = key.base64DecodeAsData();
        let cData = self.cStringUsingEncoding(NSUTF8StringEncoding)
        var result = [CUnsignedChar](count: Int(algorithm.digestLength()), repeatedValue: 0)
        let strLen = Int(strlen(cData!))
        CCHmac(algorithm.toCCHmacAlgorithm(), cKey.bytes, cKey.length, cData!, strLen, &result)
        let hmacData:NSData = NSData(bytes: result, length: (Int(algorithm.digestLength())))
        let hmacBase64 = hmacData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding76CharacterLineLength)
        return String(hmacBase64)
    }

    func base64DecodeAsData() -> NSData {
        let decodedData = NSData(base64EncodedString: self, options: NSDataBase64DecodingOptions(rawValue: 0))
        return decodedData!
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.