How to convert hexadecimal string to an array of UInt8 bytes in Swift?

后端 未结 3 677
灰色年华
灰色年华 2020-12-03 17:37

I have the following code:

var encryptedByteArray: Array?
do {
    let aes = try AES(key: \"passwordpassword\", iv: \"drowssapdrowssap\")
    e         


        
相关标签:
3条回答
  • 2020-12-03 18:03

    You can convert your hexa string back to array of UInt8 iterating every two hexa characters and initialize an UInt8 from it using UInt8 radix 16 initializer:


    Edit/update: Xcode 14 • Swift 5.1

    extension StringProtocol {
        var hexaData: Data { .init(hexa) }
        var hexaBytes: [UInt8] { .init(hexa) }
        private var hexa: UnfoldSequence<UInt8, Index> {
            sequence(state: startIndex) { startIndex in
                guard startIndex < self.endIndex else { return nil }
                let endIndex = self.index(startIndex, offsetBy: 2, limitedBy: self.endIndex) ?? self.endIndex
                defer { startIndex = endIndex }
                return UInt8(self[startIndex..<endIndex], radix: 16)
            }
        }
    }
    

    let string = "e0696349774606f1b5602ffa6c2d953f"
    let data = string.hexaData    // 16 bytes
    let bytes = string.hexaBytes  // [224, 105, 99, 73, 119, 70, 6, 241, 181, 96, 47, 250, 108, 45, 149, 63]
    

    Playground:

    let hexaString = "e0696349774606f1b5602ffa6c2d953f"
    
    let bytes = hexaString.hexa   // [224, 105, 99, 73, 119, 70, 6, 241, 181, 96, 47, 250, 108, 45, 149, 63]
    
    0 讨论(0)
  • 2020-12-03 18:09

    Based on answer from Leo Dabus

    Details

    • Swift 5.1, Xcode 11.2.1

    Solution

    enum HexConvertError: Error {
        case wrongInputStringLength
        case wrongInputStringCharacters
    }
    
    extension StringProtocol {
        func asHexArrayFromNonValidatedSource() -> [UInt8] {
            var startIndex = self.startIndex
            return stride(from: 0, to: count, by: 2).compactMap { _ in
                let endIndex = index(startIndex, offsetBy: 2, limitedBy: self.endIndex) ?? self.endIndex
                defer { startIndex = endIndex }
                return UInt8(self[startIndex..<endIndex], radix: 16)
            }
        }
    
        func asHexArray() throws -> [UInt8] {
            if count % 2 != 0 { throw HexConvertError.wrongInputStringLength }
            let characterSet = "0123456789ABCDEFabcdef"
            let wrongCharacter = first { return !characterSet.contains($0) }
            if wrongCharacter != nil { throw HexConvertError.wrongInputStringCharacters }
            return asHexArrayFromNonValidatedSource()
        }
    }
    

    Usage

    // Way 1
    do {
         print("with validation: \(try input.asHexArray() )")
    } catch (let error) {
         print("with validation: \(error)")
    }
    
    // Way 2
    "12g". asHexArrayFromNonValidatedSource()
    

    Full sample

    Do not forget to paste here the solution code

    func test(input: String) {
        print("input: \(input)")
        do {
            print("with validation: \(try input.asHexArray() )")
        } catch (let error) {
            print("with validation: \(error)")
        }
        print("without validation \(input.asHexArrayFromNonValidatedSource())\n")
    }
    
    test(input: "12wr22")
    test(input: "124")
    test(input: "12AF")
    

    Console output

    input: 12wr22
    with validation: wrongInputStringCharacters
    without validation [18, 34]
    
    input: 124
    with validation: wrongInputStringLength
    without validation [18, 4]
    
    input: 1240
    with validation: [18, 64]
    without validation [18, 64]
    
    input: 12AF
    with validation: [18, 175]
    without validation [18, 175]
    
    0 讨论(0)
  • 2020-12-03 18:30

    Swift 5

    import CryptoSwift
    
    let hexString = "e0696349774606f1b5602ffa6c2d953f"
    let hexArray = Array<UInt8>.init(hex: hexString) // [224, 105, 99, 73, 119, 70, 6, 241, 181, 96, 47, 250, 108, 45, 149, 63]
    
    0 讨论(0)
提交回复
热议问题