/** * From the Lucky13 paper: An individual record R (viewed as a byte sequence of length at least * zero) is processed as follows. The sender maintains an 8-byte sequence number SQN which is * incremented for each record sent, and forms a 5-byte field HDR consisting of a 1-byte type * field, a 2-byte version field, and a 2-byte length field. It then calculates a MAC over the * bytes SQN || HDR || R. * * @param protocolVersion * @param contentType * @param data * @return */ public byte[] calculateMac( ProtocolVersion protocolVersion, ProtocolMessageType contentType, byte[] data) { byte[] SQN = ArrayConverter.longToUint64Bytes(sequenceNumber); byte[] HDR = ArrayConverter.concatenate( contentType.getArrayValue(), protocolVersion.getValue(), ArrayConverter.intToBytes(data.length, 2)); writeMac.update(SQN); writeMac.update(HDR); writeMac.update(data); LOGGER.debug( "The MAC was caluculated over the following data: {}", ArrayConverter.bytesToHexString(ArrayConverter.concatenate(SQN, HDR, data))); byte[] result = writeMac.doFinal(); LOGGER.debug("MAC result: {}", ArrayConverter.bytesToHexString(result)); // we increment sequence number for the sent records sequenceNumber++; return result; }