【问题标题】:Creating an NDEF WiFi Record using application/vnd.wfa.wsc in Swift在 Swift 中使用 application/vnd.wfa.wsc 创建 NDEF WiFi 记录
【发布时间】:2019-09-07 10:30:42
【问题描述】:

我正在尝试在 Swift 中创建 application/vnd.wfa.wsc 有效负载。我在这里为 Android 找到了这篇文章: Creating an NDEF WiFi record using application/vnd.wfa.wsc in Android

我一直坚持创建我想在 NFC 标签上写入的有效负载。我尝试将 java 代码翻译成 swift 并将有效负载写入 NFC 标签,但我无法使用 android 手机读取数据。

let VERSION: [UInt8] = [0x10, 0x4A]
let CREDENTIAL: [UInt8] = [0x10, 0x0e]
let AUTH_TYPE: [UInt8]    = [0x10, 0x03]
let CRYPT_TYPE: [UInt8]   = [0x10, 0x0F]
let MAC_ADDRESS: [UInt8]  = [0x10, 0x20]
let NETWORK_IDX: [UInt8]  = [0x10, 0x26]
let NETWORK_KEY: [UInt8]  = [0x10, 0x27]
let NETWORK_NAME: [UInt8] = [0x10, 0x45]
let OOB_PASSWORD: [UInt8] = [0x10, 0x2C]
let VENDOR_EXT: [UInt8]   = [0x10, 0x49]
let VENDOR_WFA: [UInt8]   = [0x00, 0x37, 0x2A]
let VERSION2: [UInt8]     = [0x00]
let KEY_SHAREABLE: [UInt8] = [0x02]
let AUTH_OPEN: [UInt8] = [0x00, 0x01]
let AUTH_WPA_PERSONAL: [UInt8] = [0x00, 0x02]
let AUTH_SHARED: [UInt8] = [0x00, 0x04]
let AUTH_WPA_ENTERPRISE: [UInt8] = [0x00, 0x08]
let AUTH_WPA2_ENTERPRISE: [UInt8] = [0x00, 0x10]
let AUTH_WPA2_PERSONAL: [UInt8] = [0x00, 0x20]
let AUTH_WPA_WPA2_PERSONAL: [UInt8] = [0x00, 0x22]
let CRYPT_NONE: [UInt8] = [0x00, 0x01]
let CRYPT_WEP: [UInt8] = [0x00, 0x02]
let CRYPT_TKIP: [UInt8] = [0x00, 0x04]
let CRYPT_AES: [UInt8] = [0x00, 0x08]
let CRYPT_AES_TKIP: [UInt8] = [0x00, 0x0C]

let credential: [UInt8] = [0x00, 0x36]
let idx: [UInt8] = [0x00, 0x01, 0x01]

let ssid = "TestWifi"
let password = "Test12345"

let ssidBytes: [UInt8] = Array(ssid.utf8)
let passwordBytes: [UInt8] = Array(password.utf8)
let authBytes: [UInt8] = Array("WPA PSK".utf8)

let lengthSSID: [UInt8] = [UInt8(ssid.lengthOfBytes(using: .utf8))]
let lengthPassword: [UInt8] = [UInt8(password.lengthOfBytes(using: .utf8))]

let cred: [UInt8] = CREDENTIAL + credential
let index: [UInt8] = NETWORK_IDX + idx
let network: [UInt8] = NETWORK_NAME + lengthSSID + ssidBytes
let auth: [UInt8] = AUTH_TYPE + AUTH_WPA_PERSONAL + authBytes
let crypt: [UInt8] = CRYPT_TYPE + CRYPT_WEP + CRYPT_AES_TKIP
let netw: [UInt8] = NETWORK_KEY + lengthPassword + passwordBytes

let foo1 = cred + index
let foo2 = network + auth
let foo3 = crypt + netw

let payload = foo1 + foo2 + foo3

let type = Data(base64Encoded: "application/vnd.wfa.wsc".base64Encoded()!)!
let identifier = Data(base64Encoded: "".base64Encoded()!)!
let payloadData = Data(bytes: payload, count: payload.count)
let payload = NFCNDEFPayload(format: .media, type: type, identifier: identifier, payload: payloadData)

谁能指出我做错了什么?

【问题讨论】:

    标签: ios wifi core-nfc


    【解决方案1】:

    1) 凭证 TLV 由子 TLV[

    以下是创建有效负载的 Swift 代码。 TODO:(1)我可能需要检查所需的字节序并重新排序各个字段(2)您可能需要检查此 API 的其他参数

    import Foundation
    import Glibc
    
    /* TotalLen is count of all bytes in parenthesis.  
    
    CREDENTIAL + totallen +   
    (  
    NETWORK_IDX + Idxlen + idx  
    NETWORK_NAME + Namelen + ssidBytes  
    AUTH_TYPE + Authlen + AUTH_WPA_PERSONAL  
    CRYPT_TYPE + Cryptlen + AUTH_MIXED  
    NETWORK_KEY + Keylen + passwordBytes  
    MAC_ADDRESS + Maclen + addr  
    )  
    
    0x100E + **TotalLen** +  
    (0x1026 + 0x0001 + 01 +  
    0x1045 + 0x0008 + TestWifi +  
    0x1003 + 0x0002 + 0x0002 +  
    0x100F + 0x0002 + 0x000C (Mixed mode supporting TKIP, AES) + 
    0x1027 + 0x0009 + Test12345 +
    0x1020 + 0x0006 + address) */
    
    //Attributes
    let VERSION: [UInt8] = [0x10, 0x4A]
    let CREDENTIAL: [UInt8] = [0x10, 0x0e]
    let AUTH_TYPE: [UInt8]    = [0x10, 0x03]
    let CRYPT_TYPE: [UInt8]   = [0x10, 0x0F]
    let MAC_ADDRESS: [UInt8]  = [0x10, 0x20]
    let NETWORK_IDX: [UInt8]  = [0x10, 0x26]
    let NETWORK_KEY: [UInt8]  = [0x10, 0x27]
    let NETWORK_NAME: [UInt8] = [0x10, 0x45]
    let OOB_PASSWORD: [UInt8] = [0x10, 0x2C]
    let VENDOR_EXT: [UInt8]   = [0x10, 0x49]
    let VENDOR_WFA: [UInt8]   = [0x00, 0x37, 0x2A]
    let VERSION2: [UInt8]     = [0x00]
    let KEY_SHAREABLE: [UInt8] = [0x02]
    let AUTH_OPEN: [UInt8] = [0x00, 0x01]
    let AUTH_WPA_PERSONAL: [UInt8] = [0x00, 0x02]
    let AUTH_SHARED: [UInt8] = [0x00, 0x04]
    let AUTH_WPA_ENTERPRISE: [UInt8] = [0x00, 0x08]
    let AUTH_MIXED: [UInt8] = [0x00, 0x0C]
    let AUTH_WPA2_ENTERPRISE: [UInt8] = [0x00, 0x10]
    let AUTH_WPA2_PERSONAL: [UInt8] = [0x00, 0x20]
    let AUTH_WPA_WPA2_PERSONAL: [UInt8] = [0x00, 0x22]
    let CRYPT_NONE: [UInt8] = [0x00, 0x01]
    let CRYPT_WEP: [UInt8] = [0x00, 0x02]
    let CRYPT_TKIP: [UInt8] = [0x00, 0x04]
    let CRYPT_AES: [UInt8] = [0x00, 0x08]
    let CRYPT_AES_TKIP: [UInt8] = [0x00, 0x0C]
    
    //Values
    let idx: [UInt8] = [0x01]
    let ssid = "TestWifi"
    let ssidBytes: [UInt8] = Array(ssid.utf8)
    let password = "Test12345"
    let passwordBytes: [UInt8] = Array(password.utf8)
    let addr: [UInt8] = [0x11, 0x22, 0x33, 0x44, 0x55, 0x66]
    
    let authBytes: [UInt8] = Array("WPA PSK".utf8)
    
    //Lengths
    let Idxlen: [UInt8] = [0x00, 0x01]
    var temp = ssid.lengthOfBytes(using: .utf8)
    let Namelen: [UInt8] = [UInt8(temp >> 8), UInt8(temp)]
    let Authlen: [UInt8] = [0x00, 0x02]
    let Cryptlen: [UInt8] = [0x00, 0x02]
    temp = password.lengthOfBytes(using: .utf8)
    let Keylen: [UInt8] = [UInt8(temp >> 8), UInt8(temp)]
    let Maclen: [UInt8] = [0x00, 0x06]
    
    //Packet formation
    let id = NETWORK_IDX + Idxlen + idx
    let name = NETWORK_NAME + Namelen + ssidBytes
    let aut = AUTH_TYPE + Authlen + AUTH_WPA_PERSONAL
    let cry = CRYPT_TYPE + Cryptlen + AUTH_MIXED
    let key = NETWORK_KEY + Keylen + passwordBytes
    let mac = MAC_ADDRESS + Maclen + addr
    var payload: [UInt8] = id + name + aut + cry + key + mac
    
    //Prepend Credential Attribute header
    let totallen = payload.count
    var totallenBytes = [UInt8(totallen >> 8), UInt8(totallen)]
    var cred = CREDENTIAL + totallenBytes
    payload.insert(contentsOf:cred, at: 0)
    print(payload)```
    

    【讨论】:

    • 感谢您的回答。到目前为止我没有运气。可以发一下你的出处吗?
    • @NicoS。我不是 Swift 程序员。但是,我学习并编码。请检查以上
    【解决方案2】:

    我使用 Wi-Fi Simple Configuration Technical Specification 的 2.0.7 版创建了以下解决方案

    let type = "application/vnd.wfa.wsc".data(using: .utf8)!
    
    let authenticationTypesString = ["Open", "WPA-Personal", "Shared", "WPA-Enterprise", "WPA2-Enterprise", "WPA2-Personal"]
    let encryptionTypesString = ["None", "WEP", "TKIP", "AES", "AES/TKIP (mixed)"]
    
    let authenticationTypes: [[UInt8]] = [[0x00, 0x01], [0x00, 0x02], [0x00, 0x04], [0x00, 0x08], [0x00, 0x10], [0x00, 0x20]]
    let encryptionTypes: [[UInt8]] = [[0x00, 0x01], [0x00, 0x02], [0x00, 0x04], [0x00, 0x08], [0x00, 0x0c]]
    
    let ssidString = "Network Name"
    let networkKeyString = "Network Key"
    
    let ssidBytes: [UInt8] = Array(ssidString.utf8)
    let networkKeyBytes: [UInt8] = Array(networkKeyString.utf8)
    
    let ssidLength = UInt8(ssidBytes.count)
    let networkKeyLength = UInt8(networkKeyBytes.count)
    
    let authenticationTypeBytes = authenticationTypes[5]
    let encryptionTypeBytes = encryptionTypes[3]
    
    let networkIndex: [UInt8]       = [0x10, 0x26, 0x00, 0x01, 0x01]
    let ssid: [UInt8]               = [0x10, 0x45, 0x00, ssidLength] + ssidBytes
    let authenticationType: [UInt8] = [0x10, 0x03, 0x00, 0x02] + authenticationTypeBytes
    let encryptionType: [UInt8]     = [0x10, 0x0F, 0x00, 0x02] + encryptionTypeBytes
    let networkKey: [UInt8]         = [0x10, 0x27, 0x00, networkKeyLength] + networkKeyBytes
    let macAddress: [UInt8]         = [0x10, 0x20, 0x00, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]
    
    let credential = networkIndex + ssid + authenticationType + encryptionType + networkKey + macAddress
    let credentialLength = UInt8(credential.count)
    
    let bytes = [0x10, 0x0E, 0x00, credentialLength] + credential
    let payload = Data(bytes: bytes, count: bytes.count)
    
    let ndefPayload = NFCNDEFPayload(format: .media, type: type, identifier: Data(), payload: payload)
    
    let ndefMessage = NFCNDEFMessage(records: [ndefPayload])
    

    我希望这会有所帮助!

    【讨论】:

      【解决方案3】:

      原始 Android 代码显示 lengthSSID 和 lengthPassword 是 2 字节数组,MSB 在第一个元素中,LSB 在第二个元素中。您的代码正在为这两个创建单个元素 [UInt8],因此二进制格式不匹配。此代码会将 SSID 长度值填充到 2 个字节:

      let lengthSSIDVal = ssid.lengthOfBytes(using: .utf8)
      let lengthSSID: [UInt8] = [UInt8(lengthSSIDVal / 256), UInt8(lengthSSIDVal % 256)]
      

      对 lengthPassword 执行相同操作。

      其余代码看起来像是一个准确的端口,所以我怀疑是上面的问题,但还要确保 NDEF 是使用 application/vnd.wfa.wsc MIME 类型编写的。

      【讨论】:

      • 您好,感谢您的回答。我尝试了您提到的修复,但它不起作用......为了更清楚,我还添加了有效负载创建。
      • 回顾链接解决方案的几件事:(1)您是否也在创建和预先设置移交选择记录? (2) 根据规范,auth 和 crypt 字段看起来是错误的,它们应该只有一个值。尝试在每一行中删除第二个值。
      • (1) 我不明白你的意思,(2) 完成了,没有帮助
      • 您能否通过使用 TagInfo 应用程序 (apps.apple.com/us/app/nfc-taginfo-by-nxp/id1246143596) 或类似应用程序读取卡片转储来发布卡片转储
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多