将十六进制编码的String转换为String

时间:2017-01-05 12:45:34

标签: swift character-encoding swift3

我想在Swift 3中转换以下十六进制编码的String

dcb04a9e103a5cd8b53763051cef09bc66abe029fdebae5e1d417e2ffc2a07a4

等同于String

Ü°J:\ص7cï  ¼f«à)ýë®^A~/ü*¤

以下网站的工作非常好:

http://codebeautify.org/hex-string-converter

http://string-functions.com/hex-string.aspx

但我无法在Swift 3中做同样的事情。以下代码也不能完成这项工作:

func convertHexStringToNormalString(hexString:String)->String!{
  if let data = hexString.data(using: .utf8){
      return String.init(data:data, encoding: .utf8)
  }else{ return nil}
}

3 个答案:

答案 0 :(得分:6)

您的代码没有按照您的想法执行。这一行:

如果让data = hexString.data(使用:.utf8){

表示“将这些字符编码为UTF-8”。这意味着“01”不编码为0x01(1),它编码为0x30 0x31(“0”“1”)。那里没有“十六进制”。

这一行:

  return String.init(data:data, encoding: .utf8)

只需获取编码的UTF-8数据,将其解释为UTF-8,然后返回。这两种方法是对称的,所以你应该期望整个函数返回它所传递的任何东西。

将Martin和Larme的评论汇总到一个地方。这似乎是用Latin-1编码的。 (这是对这些数据进行编码的一种非常尴尬的方式,但如果它正是您所寻找的,我认为这就是编码。)

import Foundation

extension Data {

    // From http://stackoverflow.com/a/40278391:
    init?(fromHexEncodedString string: String) {

        // Convert 0 ... 9, a ... f, A ...F to their decimal value,
        // return nil for all other input characters
        func decodeNibble(u: UInt16) -> UInt8? {
            switch(u) {
            case 0x30 ... 0x39:
                return UInt8(u - 0x30)
            case 0x41 ... 0x46:
                return UInt8(u - 0x41 + 10)
            case 0x61 ... 0x66:
                return UInt8(u - 0x61 + 10)
            default:
                return nil
            }
        }

        self.init(capacity: string.utf16.count/2)
        var even = true
        var byte: UInt8 = 0
        for c in string.utf16 {
            guard let val = decodeNibble(u: c) else { return nil }
            if even {
                byte = val << 4
            } else {
                byte += val
                self.append(byte)
            }
            even = !even
        }
        guard even else { return nil }
    }
}

let d = Data(fromHexEncodedString: "dcb04a9e103a5cd8b53763051cef09bc66abe029fdebae5e1d417e2ffc2a07a4")!
let s = String(data: d, encoding: .isoLatin1)

答案 1 :(得分:3)

您希望将十六进制编码数据用作AES密钥,但是 数据不是有效的UTF-8序列。你可以解释 它是ISO拉丁语编码中的字符串,但是AES(key: String, ...) 初始化程序将字符串转换回其UTF-8表示形式, 即,您将获得与您开始时不同的关键数据。

因此,您根本不应将其转换为字符串。使用

extension Data {
    init?(fromHexEncodedString string: String)
}
来自hex/binary string conversion in Swift

方法 将十六进制编码的字符串转换为Data,然后传递它 作为AES(key: Array<UInt8>, ...)初始值设定项的数组:

let hexkey = "dcb04a9e103a5cd8b53763051cef09bc66abe029fdebae5e1d417e2ffc2a07a4"
let key = Array(Data(fromHexEncodedString: hexkey)!)

let encrypted = try AES(key: key, ....)

答案 2 :(得分:0)

仍然可以通过添加以下扩展名来将密钥从十六进制转换为可读字符串:

extension String {
    
    func hexToString()->String{
        
        var finalString = ""
        let chars = Array(self)
        
        for count in stride(from: 0, to: chars.count - 1, by: 2){
            let firstDigit =  Int.init("\(chars[count])", radix: 16) ?? 0
            let lastDigit = Int.init("\(chars[count + 1])", radix: 16) ?? 0
            let decimal = firstDigit * 16 + lastDigit
            let decimalString = String(format: "%c", decimal) as String
            finalString.append(Character.init(decimalString))
        }
        return finalString
        
    }
    
    func base64Decoded() -> String? {
        guard let data = Data(base64Encoded: self) else { return nil }
        return String(data: data, encoding: .init(rawValue: 0))
    }
}

使用示例:

    let hexToString = secretKey.hexToString()
    let base64ReadableKey = hexToString.base64Decoded() ?? ""