1package com.peachpasswords.sync2345678910111213141516171819object SyncPadding {20 private const val HEADER_BYTES = 42122 23 private const val MIN_BUCKET = 2562425 26272829 private const val LINEAR_BUCKET_STEP = 64 * 10243031 fun bucket(totalBytes: Int): Int {32 if (totalBytes <= MIN_BUCKET) return MIN_BUCKET33 if (totalBytes <= LINEAR_BUCKET_STEP) {34 var b = MIN_BUCKET35 while (b < totalBytes) b *= 236 return b37 }38 return ((totalBytes + LINEAR_BUCKET_STEP - 1) / LINEAR_BUCKET_STEP) * LINEAR_BUCKET_STEP39 }4041 fun pad(payload: ByteArray): ByteArray {42 val out = ByteArray(bucket(HEADER_BYTES + payload.size))43 val len = payload.size44 out[0] = (len ushr 24).toByte()45 out[1] = (len ushr 16).toByte()46 out[2] = (len ushr 8).toByte()47 out[3] = len.toByte()48 payload.copyInto(out, HEADER_BYTES)49 return out50 }5152 fun unpad(padded: ByteArray): ByteArray {53 require(padded.size >= HEADER_BYTES) {54 "padded sync frame is shorter than its length header"55 }56 val length = ((padded[0].toInt() and 0xFF) shl 24) or57 ((padded[1].toInt() and 0xFF) shl 16) or58 ((padded[2].toInt() and 0xFF) shl 8) or59 (padded[3].toInt() and 0xFF)60 require(length >= 0 && length <= padded.size - HEADER_BYTES) {61 "padded sync frame declares more payload than it carries"62 }63 return padded.copyOfRange(HEADER_BYTES, HEADER_BYTES + length)64 }65}