session-ios/SessionMessagingKit/Utilities/Data+Utilities.swift

56 lines
2.0 KiB
Swift

// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import SessionUtilitiesKit
// MARK: - Decoding
public extension Data {
func removePadding() -> Data {
let bytes: [UInt8] = self.bytes
var paddingStart: Int = self.count
for i in 0..<(self.count - 1) {
let targetIndex: Int = ((self.count - 1) - i)
if bytes[targetIndex] == 0x80 {
paddingStart = targetIndex
break
}
else if bytes[targetIndex] != 0x00 {
SNLog("Failed to remove padding, returning unstripped padding");
return self
}
}
return self.prefix(upTo: paddingStart)
}
func paddedMessageBody() -> Data {
// From
// https://github.com/signalapp/TextSecure/blob/master/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/push/PushTransportDetails.java#L55
// NOTE: This is dumb. We have our own padding scheme, but so does the cipher.
// The +1 -1 here is to make sure the Cipher has room to add one padding byte,
// otherwise it'll add a full 16 extra bytes.
let paddedMessageLength: Int = (self.paddedMessageLength(self.count + 1) - 1)
var paddedMessage: Data = Data(count: paddedMessageLength)
let paddingByte: UInt8 = 0x80
paddedMessage[0..<self.count] = Data(self.bytes)
paddedMessage[self.count..<(self.count + 1)] = Data([paddingByte])
return paddedMessage
}
private func paddedMessageLength(_ unpaddedLength: Int) -> Int {
let messageLengthWithTerminator: Int = (unpaddedLength + 1)
var messagePartCount: Int = (messageLengthWithTerminator / 160)
if CGFloat(messageLengthWithTerminator).truncatingRemainder(dividingBy: 160) != 0 {
messagePartCount += 1
}
return (messagePartCount * 160)
}
}