0

I'm having issues working with iOS Swift 2.0 to perform an XOR on a [UInt8] and convert the XORd result to a String. I'm having to interface with a crude server that wants to do simple XOR encryption with a predefined array of UInt8 values and return that result as a String.

Using iOS Swift 2.0 Playground, create the following array:

let xorResult : [UInt8] = [24, 48, 160, 212]   // XORd result
let result = NSString(bytes: xorResult, length: xorResult.count, encoding: NSUTF8StringEncoding)

The result is always nil. If you remove the 160 and 212 values from the array, NSString is not nil. If I switch to NSUTF16StringEncoding then I do not receive nil, however, the server does not support UTF16. I have tried converting the values to a hex string, then converting the hex string to NSData, then try to convert that to NSUTF8StringEncoding but still nil until I remove the 160 and 212. I know this algorithm works in Java, however in Java we're using a combination of char and StringBuilder and everything is happy. Is there a way around this in iOS Swift?

Josh
  • 2,955
  • 1
  • 19
  • 28
  • `24, 48, 160, 212` is not a valid UTF-8 sequence. What string exactly do you (or the server) expect as the result? – Martin R Dec 28 '15 at 15:42
  • Just a string representation of an XORd result. The app we're having to interface with uses the XOR result as "encryption" to build a QR-Code. They provided us an array similar to the following, just larger: private let encryptTable : [UInt8] = [ 0x39, 0x56, 0x5F, 0xD3, 0xBC, 0x67, 0xA7, 0xCF ] I have to randomize an index in this array, then XOR from the encryptTable against each character in the String value. – Josh Dec 28 '15 at 15:45
  • Try `NSASCIIStringEncoding` instead. – luk2302 Dec 28 '15 at 15:45
  • @luk2302 that's the fix. Thanks a bunch. Make your comment an answer and I'll up vote it. – Josh Dec 28 '15 at 15:51
  • NSASCIIStringEncoding is officially a 7-bit encoding only, but it behaves like NSISOLatin1StringEncoding with 8-bit input (observed here: http://stackoverflow.com/a/32695683/1187415), so I would recommend the latter. – Martin R Dec 28 '15 at 15:52
  • I'm new to iOS Swift. This may be off topic, but do you have any suggestions for reading on how Swift handles all these encodings? I found the Swift guide and I've found their equivalent of Javadocs, but none of it really gets into the meet of this stuff. I've figured out the easy stuff, but the in-depth areas of Swift I'm learning from searching StackOverflow questions. – Josh Dec 28 '15 at 15:55
  • Since I do not really have any idea about encoding neither I will not post it as an answer, if anyone then @MartinR should post it. – luk2302 Dec 28 '15 at 15:56
  • @Josh: *How* do you send the string to the server? – Martin R Dec 28 '15 at 16:03
  • I don't send the string to directly to the server. This XOR "encryption" builds a string for a QR-Code. I need to take string data, use this XOR array table to XOR each character in that string, then generate a QR-Code from the XORd string result. That QR-Code is then scanned by a third party app that sends it to their server. The third party established this crude XOR method so we have no control over using this XOR logic, we have to do it or their app can't parse the QR-Code scan result. So far, using the NSISOLatin1StringEncoding is working for all of test values they sent us. – Josh Dec 28 '15 at 16:14

1 Answers1

2

To store an arbitrary chunk of binary data as as a string, you need a string encoding which maps each single byte (0 ... 255) to some character. UTF-8 does not have this property, as for example 160 is the start of a multi-byte UTF-8 sequence and not valid on its own.

The simplest encoding with this property is the ISO Latin 1 aka ISO 8859-1, which is the ISO/IEC 8859-1 encoding when supplemented with the C0 and C1 control codes. It maps the Unicode code points U+0000 .. U+00FF to the bytes 0x00 .. 0xFF (compare 8859-1.TXT).

This encoding is available for (NS)String as NSISOLatin1StringEncoding.

Please note: The result of converting an arbitrary binary chunk to a (NS)String with NSISOLatin1StringEncoding will contain embedded NUL and control characters. Some functions behave unexpectedly when used with such a string. For example, NSLog() terminates the output at the first embedded NUL character. This conversion is meant to solve OP's concrete problem (creating a QR-code which is recognized by a 3rd party application). It is not meant as a universal mechanism to convert arbitrary data to a string which may be printed or presented in any way to the user.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Note that the ISO/IEC 8859-1 encoded characters in the ranges `0x00` - `0x1f` and `0x7f` - `0x9f` are undefined and may not map the printable characters. – zaph Dec 28 '15 at 17:07