Checksum and XOR in Swift - ios

I worte these methods in Objective-C. They're just checksum and XOR some NSData
- (void)XOR:(NSMutableData *)inputData withKey:(NSData *)key
{
unsigned char* inputByteData = (unsigned char*)[inputData mutableBytes];
unsigned char* keyByteData = (unsigned char*)[key bytes];
for (int i = 0; i < [inputData length]; i++)
{
inputByteData[i] = inputByteData[i] ^ keyByteData[i % [key length]];
}
}
- (Byte)checkSum:(NSMutableData *)data withLength:(Byte)dataLength
{
Byte * dataByte = (Byte *)malloc(dataLength);
memcpy(dataByte, [data bytes], dataLength);
Byte result = 0;
int count = 0;
while (dataLength>0) {
result += dataByte[count];
dataLength--;
count++;
};
result = result&0xff;
return result&0xff;
}
However, I'm not familiar with Bitwise operators, especially in Swift, with these UnsafeMutablePointer<Void>... things.
Can anybody help me converting this ? (Basically, I need checksum and XOR functions)
One more things, should they be put in NSData/NSMutableData extension ?
Thank you.

UnsafeBufferPointer/UnsafeMutableBufferPointer might be what you need now. I've tried translating your code into Swift below. (But the code is not tested well.)
func XOR(inputData: NSMutableData, withKey key: NSData) {
let b = UnsafeMutableBufferPointer<UInt8>(start:
UnsafeMutablePointer(inputData.mutableBytes), count: inputData.length)
let k = UnsafeBufferPointer<UInt8>(start:
UnsafePointer(key.bytes), count: key.length)
for i in 0..<inputData.length {
b[i] ^= k[i % key.length]
}
}
func checkSum(data: NSData) -> Int {
let b = UnsafeBufferPointer<UInt8>(start:
UnsafePointer(data.bytes), count: data.length)
var sum = 0
for i in 0..<data.length {
sum += Int(b[i])
}
return sum & 0xff
}

Swift 3 update:
public extension Data {
public mutating func xor(key: Data) {
for i in 0..<self.count {
self[i] ^= key[i % key.count]
}
}
public func checkSum() -> Int {
return self.map { Int($0) }.reduce(0, +) & 0xff
}
}
You can also create another function: xored(key: Data) -> Data.
Then you can chain these operators: xored(key).checksum()

Swift support operator overloading, so you can easily do let xorData = data1 ^ data2. I have written an extension for non-similar size data to xor.
extension Data {
static func ^ (left: Data, right: Data) -> Data {
if left.count != right.count {
NSLog("Warning! XOR operands are not equal. left = \(left), right = \(right)")
}
var result: Data = Data()
var smaller: Data, bigger: Data
if left.count <= right.count {
smaller = left
bigger = right
} else {
smaller = right
bigger = left
}
let bs:[UInt8] = Array(smaller)
let bb:[UInt8] = Array (bigger)
var br = [UInt8] ()
for i in 0..<bs.count {
br.append(bs[i] ^ bb[i])
}
for j in bs.count..<bb.count {
br.append(bb[j])
}
result = Data(br)
return result
}
}

Updated for Swift 3:
func xor(data: Data, with key: Data) -> Data {
var xorData = data
xorData.withUnsafeMutableBytes { (start: UnsafeMutablePointer<UInt8>) -> Void in
key.withUnsafeBytes { (keyStart: UnsafePointer<UInt8>) -> Void in
let b = UnsafeMutableBufferPointer<UInt8>(start: start, count: xorData.count)
let k = UnsafeBufferPointer<UInt8>(start: keyStart, count: data.count)
let length = data.count
for i in 0..<xorData.count {
b[i] ^= k[i % length]
}
}
}
return xorData
}

Related

Converting bytes to floats in Swift when receiving bluetooth communications [duplicate]

This is my code to convert byte data to float. I tried every answers given in this site. I am getting exponential value for this "<44fa0000>" byte data
static func returnFloatValue(mutableData:NSMutableData)->Float
{
let qtyRange = mutableData.subdataWithRange(NSMakeRange(0, 4))
let qtyString = String(qtyRange)
let qtyTrimString = qtyString.stringByTrimmingCharactersInSet(NSCharacterSet(charactersInString: "<>"))
let qtyValue = Float(strtoul(qtyTrimString, nil, 16)/10)
return qtyValue
}
Thanks
<44fa0000> is the big-endian memory representation of the
binary floating point number 2000.0. To get the number back from
the data, you have to read it into an UInt32 first, convert from
big-endian to host byteorder, and then cast the result to
a Float.
In Swift 2 that would be
func floatValueFromData(data: NSData) -> Float {
return unsafeBitCast(UInt32(bigEndian: UnsafePointer(data.bytes).memory), Float.self)
}
Example:
let bytes: [UInt8] = [0x44, 0xFA, 0x00, 0x00]
let data = NSData(bytes: bytes, length: 4)
print(data) // <44fa0000>
let f = floatValueFromData(data)
print(f) // 2000.0
In Swift 3 you would use Data instead of NSData, and the
unsafeBitCast can be replaced by the Float(bitPattern:)
initializer:
func floatValue(data: Data) -> Float {
return Float(bitPattern: UInt32(bigEndian: data.withUnsafeBytes { $0.pointee } ))
}
In Swift 5 the withUnsafeBytes() method of Data calls the closure with an (untyped) UnsafeRawBufferPointer, and you can load() the value from the raw memory:
func floatValue(data: Data) -> Float {
return Float(bitPattern: UInt32(bigEndian: data.withUnsafeBytes { $0.load(as: UInt32.self) }))
}
Here is some swift 5:
let data = Data([0x44, 0xfa, 0x00, 0x00]) // 0x44fa0000
let floatNb:Float = data.withUnsafeBytes { $0.load(as: Float.self) }
// note that depending on the input endianess, you could add .reversed() to data
let floatNb:Float = data.reversed().withUnsafeBytes { $0.load(as: Float.self) }
WARNING: this sample throws if your Data is under 4 bytes..
.
Safe Data extension:
extension Data {
enum Endianess {
case little
case big
}
func toFloat(endianess: Endianess = .little) -> Float? {
guard self.count <= 4 else { return nil }
switch endianess {
case .big:
let data = [UInt8](repeating: 0x00, count: 4-self.count) + self
return data.withUnsafeBytes { $0.load(as: Float.self) }
case .little:
let data = self + [UInt8](repeating: 0x00, count: 4-self.count)
return data.reversed().withUnsafeBytes { $0.load(as: Float.self) }
}
}
}
Tests:
let opData = Data([0x44, 0xFA, 0x00, 0x00])
let nb42 = Data([0x42, 0x28])
let nb42bigEndian = Data([0x28, 0x42])
let tooBig = Data([0x44, 0xFA, 0x00, 0x00, 0x00])
print("opData: \(opData.toFloat())")
print("nb42: \(nb42.toFloat())")
print("nb42bigEndian: \(nb42bigEndian.toFloat(endianess: .big))")
print("tooBig: \(tooBig.toFloat())")
you may find a faster way but this was good enough for my needs
Use this function:
static func returnFloatValue(data: NSMutableData) -> Float {
let bytes = [UInt8](data as Data)
var f: Float = 0
memcpy(&f, bytes, 4)
return f
}
And you can see it in action here:
var initialValue: Float = 19.200
let data = NSMutableData(bytes: &initialValue, length: 4)
func returnFloatValue(data: NSMutableData) -> Float {
let bytes = [UInt8](data as Data)
var f: Float = 0
memcpy(&f, bytes, 4)
return f
}
var result:Float = returnFloatValue(data: data)
print("f=\(result)")// f=19.2
For 64 bit values the code is:
static func longBitsToDouble(x : Int64) -> Float64
{ return Float64(bitPattern: UInt64(x)) }
Swift 4+.

How to calculate checksum in swift?

I want to calculate checksum. My expected answer of crc is 0xE1
But when I run this code it returns 0. I am not getting any solution to do this. Please help me to solve this.
Below is my tried code.
My viewController:
class ViewController: UIViewController {
var checkSum:UInt8 = 0
override func viewDidLoad() {
super.viewDidLoad()
let bytes = [0x01,0x0B,0x00,0x0B,0x03,0x07,0x12,0x0E,0x0C,0x10,0x09,0x12,0x0C,0x19,0x09,0xFF,0x14]
for item in bytes {
print(calculateCheckSum(crc: checkSum, byteValue: UInt8(item)))
}
}
func calculateCheckSum(crc:UInt8, byteValue: UInt8) -> UInt8 {
let generator = 0x1D
checkSum = crc ^ byteValue
for _ in 1...8 {
if (crc & 0x80 != 0) {
checkSum = (crc << 1) ^ UInt8(Int8(generator))
}
else {
checkSum <<= UInt8(1)
}
}
return crc
}
}
Rewritten to avoid incorrectly using the global checkSum variable.
func calculateCheckSum(crc:UInt8, byteValue: UInt8) -> UInt8 {
let generator: UInt8 = 0x1D
// a new variable has to be declared inside this function
var newCrc = crc ^ byteValue
for _ in 1...8 {
if newCrc & 0x80 != 0 {
newCrc = (newCrc << 1) ^ generator
}
else {
newCrc <<= 1
}
}
return newCrc
}
Also, it seems you are not using the result of the method correctly:
var checkSum: UInt8 = 0
let bytes = [...]
for item in bytes {
checkSum = calculateCheckSum(crc: checkSum, byteValue: UInt8(item))
}
print(checkSum)
I just made an extension from this github link and it works to get CRC32 checksum in case anyone needs it.
extension Data {
public func checksum() -> UInt32 {
let table: [UInt32] = {
(0...255).map { i -> UInt32 in
(0..<8).reduce(UInt32(i), { c, _ in
(c % 2 == 0) ? (c >> 1) : (0xEDB88320 ^ (c >> 1))
})
}
}()
return ~(self.bytes.reduce(~UInt32(0), { crc, byte in
(crc >> 8) ^ table[(Int(crc) ^ Int(byte)) & 0xFF]
}))
} }

How to convert convert [String] to [UInt8] in swift?

How to convert my stringArray to int8Array. Please give me any solution to convert this.
I want below type of array
let int8Array:[UInt8] = [ox55,0x55,0xff,0x01,0x0B,0x00,0x0B,0x03,0x07,0x12,0x0E,0x0C,0x10,0x09,0x12,0x0C,0x19,0x09,0xFF,0x14]
Below is my ViewController:
class ViewController:UIViewController {
var checkSum:UInt8 = 0
override func viewDidLoad() {
super.viewDidLoad()
let stringArray:[String] = ["0x55", "0x55", "0xff", "0x01", "0x0B", "0x38", "0x18", "0x31", "0x10", "0x18", "0x0E", "0x16", "0x31", "0x10", "0x18", "0x16", "0x30", "0x11", "0x18", "0x20", "0xE1"]
var int8Array:[UInt8] = stringArray.map{ UInt8($0.dropFirst(2), radix: 16)! }
int8Array.removeFirst()
int8Array.removeFirst()
int8Array.removeFirst()
print(int8Array)
for item in int8Array {
checkSum = calculateCheckSum(crc: checkSum, byteValue: UInt8(item))
}
print(checkSum)
}
func calculateCheckSum(crc:UInt8, byteValue: UInt8) -> UInt8 {
let generator: UInt8 = 0x1D
var newCrc = crc ^ byteValue
for _ in 1...8 {
if (newCrc & 0x80 != 0) {
newCrc = (newCrc << 1) ^ generator
}
else {
newCrc <<= 1
}
}
return newCrc
}
}
If it is an option you could switch it around to specify the UInt8 array and derive the String array from that.
let int8Array: [UInt8] = [0x55, 0x55, 0xa5, 0x3f]
var stringArray: [String] {
return int8Array.map { String(format: "0x%02X", $0) }
}
print(stringArray)
// ["0x55", "0x55", "0xA5", "0x3F"]
Just map the stuff, you have to remove 0x to make the UInt8(_:radix:) initializer work.
let uint8Array = stringArray.map{ UInt8($0.dropFirst(2), radix: 16)! }
First take your string array and call map on it then map it to a [UInt8] (where the total result will be [[UInt8]] and call flatMap on the result to get an array of [UInt8].. then you can do forEach on it to calculate your checksum or w/e..
[String].init().map({
[UInt8]($0.utf8)
}).flatMap({ $0 }).forEach({
print($0) //Print each byte or convert to hex or w/e..
})

How can split from string to array by chunks of given size

I want to split string by chunks of given size 2
Example :
String "1234567" and output should be ["12", "34", "56","7"]
You can group your collection elements (in this case Characters) every n elements as follow:
extension Collection {
func unfoldSubSequences(limitedTo maxLength: Int) -> UnfoldSequence<SubSequence,Index> {
sequence(state: startIndex) { start in
guard start < self.endIndex else { return nil }
let end = self.index(start, offsetBy: maxLength, limitedBy: self.endIndex) ?? self.endIndex
defer { start = end }
return self[start..<end]
}
}
func subSequences(of n: Int) -> [SubSequence] {
.init(unfoldSubSequences(limitedTo: n))
}
}
let numbers = "1234567"
let subSequences = numbers.subSequences(of: 2)
print(subSequences) // ["12", "34", "56", "7"]
edit/update:
If you would like to append the exceeding characters to the last group:
extension Collection {
func unfoldSubSequencesWithTail(lenght: Int) -> UnfoldSequence<SubSequence,Index> {
let n = count / lenght
var counter = 0
return sequence(state: startIndex) { start in
guard start < endIndex else { return nil }
let end = index(start, offsetBy: lenght, limitedBy: endIndex) ?? endIndex
counter += 1
if counter == n {
defer { start = endIndex }
return self[start...]
} else {
defer { start = end }
return self[start..<end]
}
}
}
func subSequencesWithTail(n: Int) -> [SubSequence] {
.init(unfoldSubSequencesWithTail(lenght: n))
}
}
let numbers = "1234567"
let subSequencesWithTail = numbers.subSequencesWithTail(n: 2)
print(subSequencesWithTail) // ["12", "34", "567"]
var testString = "abcdefghijklmnopqrstu"
var startingPoint: Int = 0
var substringLength: Int = 1
var substringArray = [AnyHashable]()
for i in 0..<(testString.count ?? 0) / substringLength {
var substring: String = (testString as NSString).substring(with: NSRange(location: startingPoint, length: substringLength))
substringArray.append(substring)
startingPoint += substringLength
}
print("\(substringArray)")
OutPut :
(
a,
b,
c,
d,
e,
f,
g,
h,
i,
j,
k,
l,
m,
n,
o,
p,
q,
r,
s,
t,
u
)
try this
func SplitString(stringToBeSplitted:String, By:Int) -> [String]
{
var newArray = [String]()
var newStr = String()
for char in stringToBeSplitted
{
newStr += String(char)
if newStr.count == By
{
newArray.append(newStr)
newStr = ""
}
}
return newArray
}
Swift 5
extension Array {
func chunks(size: Int) -> [[Element]] {
return stride(from: 0, to: count, by: size).map {
Array(self[$0 ..< Swift.min($0 + size, count)])
}
}
}
extension String {
func chunks(size: Int) -> [String] {
map { $0 }.chunks(size: size).compactMap { String($0) }
}
}
let s = "1234567"
print(s.chunks(size: 2)) // ["12", "34", "56", "7"]
extension String {
func split(len: Int) -> [String] {
var currentIndex = 0
var array = [String]()
let length = self.characters.count
while currentIndex < length {
let startIndex = self.startIndex.advancedBy(currentIndex)
let endIndex = startIndex.advancedBy(len, limit: self.endIndex)
let substr = self.substringWithRange(Range(start: startIndex, end: endIndex))
array.append(substr)
currentIndex += len
}
return array
}
}
"123456789".split(2)
//output: ["12", "34", "56", "78", "9"]
I have write one method in objective c as below,
-(NSMutableArray*)splitString : (NSString*)str withRange : (int)range{
NSMutableArray *arr = [[NSMutableArray alloc]init];
NSMutableString *mutableStr = [[NSMutableString alloc]initWithString:str];
int j = 0;
int counter = 0;
for (int i = 0; i < str.length; i++) {
j++;
if (range == j) {
j = 0;
if (!(i == str.length - 1)) {
[mutableStr insertString:#"$" atIndex:i+1+counter];
}
counter++;
}
}
arr = (NSMutableArray*)[mutableStr componentsSeparatedByString:#"$"];
NSLog(#"%#",arr);
return arr;
}
You can call this method like,
[self splitString:#"123456" withRange:2];
and result will be,
(
12,
34,
56
)
You can also try below code:
var arrStr: [Substring] = []
let str = "1234567"
var i = 0
while i < str.count - 1 {
let index = str.index(str.startIndex, offsetBy: i)
//Below line gets current index and advances by 2
let substring = str[index..<str.index(index, offsetBy: 2)]
arrStr.append(substring)
i += 2
}
if str.count % 2 == 1 {
arrStr.append(str.suffix(1))
}
print(arrStr)
There's a stupid way, you can think about the rules of the data model.
var strOld = "123456"
print("The original string:\(strOld)")
strOld.insert("、", at: strOld.index(before: strOld.index(strOld.startIndex, offsetBy: 3)))
strOld.insert("、", at: strOld.index(before: strOld.index(strOld.startIndex, offsetBy: 6)))
print("After inserting:\(strOld)")
let str = strOld
let splitedArray = str.components(separatedBy: "、")
print("After the split of the array:\(splitedArray)")
let splitedArrayOther = str.split{$0 == "、"}.map(String.init)
print("After break up the array (method 2):\(splitedArrayOther)")
The results:
The original string:123456
After inserting:12、34、56
After the split of the array:["12", "34", "56"]
After break up the array (method 2):["12", "34", "56"]
Here's a short (and clean) solution, thanks to recursion:
extension Collection {
func chunks(ofSize size: Int) -> [SubSequence] {
// replace this by `guard count >= size else { return [] }`
// if you want to omit incomplete chunks
guard !isEmpty else { return [] }
return [prefix(size)] + dropFirst(size).chunks(ofSize: size)
}
}
The recursion should not pose a performance problem, as Swift has support for tail call optimization.
Also if Swift arrays are really fast when it comes to prepending or appending elements (like the Objective-C ones are), then the array operations should be fast.
Thus you get both fast and readable code (assuming my array assumptions are true).

How to convert AnyBase to Base10?

I found some code to encode a Base10-String with to a custom BaseString:
func stringToCustomBase(encode: Int, alphabet: String) -> String {
var base = alphabet.count, int = encode, result = ""
repeat {
let index = alphabet.index(alphabet.startIndex, offsetBy: (int % base))
result = [alphabet[index]] + result
int /= base
} while (int > 0)
return result
}
... calling it with this lines:
let encoded = stringToCustomBase(encode: 9291, alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
print(encoded)
The encoding above works pretty good. But what about decoding the encoded string?
So because I got no idea how to decode a (in this case Base62 [alphabet.count=62]) to a human readable string (in this case [Base10]) any help would be super appreciated.
PS: (A full code solution is not required, I can also come up with some kind of pseudo-code or maybe just a few-lines of code)
This is what I've tried so far:
func reVal(num: Int) -> Character {
if (num >= 0 && num <= 9) {
return Character("\(num)")
}
return Character("\(num - 10)A");
}
func convertBack() {
var index = 0;
let encoded = "w2RDn3"
var decoded = [Character]()
var inputNum = encoded.count
repeat {
index+=1
decoded[index] = reVal(num: inputNum % 62)
//encoded[index] = reVal(inputNum % 62);
inputNum /= 62;
} while (inputNum > 0)
print(decoded);
}
Based on the original algorithm you need to iterate through each character of the encoded string, find the location of that character within the alphabet, and calculate the new result.
Here are both methods and some test code:
func stringToCustomBase(encode: Int, alphabet: String) -> String {
var base = alphabet.count, string = encode, result = ""
repeat {
let index = alphabet.index(alphabet.startIndex, offsetBy: (string % base))
result = [alphabet[index]] + result
string /= base
} while (string > 0)
return result
}
func customBaseToInt(encoded: String, alphabet: String) -> Int? {
let base = alphabet.count
var result = 0
for ch in encoded {
if let index = alphabet.index(of: ch) {
let mult = result.multipliedReportingOverflow(by: base)
if (mult.overflow) {
return nil
} else {
let add = mult.partialValue.addingReportingOverflow(alphabet.distance(from: alphabet.startIndex, to: index))
if (add.overflow) {
return nil
} else {
result = add.partialValue
}
}
} else {
return nil
}
}
return result
}
let startNum = 234567
let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let codedNum = stringToCustomBase(encode: startNum, alphabet: alphabet)
let origNun = customBaseToInt(encoded: codedNum, alphabet: alphabet)
I made the customBaseToInt method return an optional result in case there are characters in the encoded value that are not in the provided alphabet.
You can achieve this via reduce:
enum RadixDecodingError: Error {
case invalidCharacter
case overflowed
}
func customRadixToInt(str: String, alphabet: String) throws -> Int {
return try str.reduce(into: 0) {
guard let digitIndex = alphabet.index(of: $1) else {
throw RadixDecodingError.invalidCharacter
}
let multiplied = $0.multipliedReportingOverflow(by: alphabet.count)
guard !multiplied.overflow else {
throw RadixDecodingError.overflowed
}
let added = multiplied.partialValue.addingReportingOverflow(alphabet.distance(from: alphabet.startIndex, to: digitIndex))
guard !added.overflow else {
throw RadixDecodingError.overflowed
}
$0 = added.partialValue
}
}
I used the exception throwing mechanism so that the caller can distinguish between invalid characters or overflow errors.

Resources