/******************************************************************************* * Copyright 2014 Trevor Robinson * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.scurrilous.circe.params; import com.scurrilous.circe.HashParameters; /** * Hash parameters used to define a <a * href="http://en.wikipedia.org/wiki/Cyclic_redundancy_check">cyclic redundancy * check</a> (CRC). Includes some commonly used sets of parameters. */ public class CrcParameters implements HashParameters { private final String name; private final int bitWidth; private final long polynomial; private final long initial; private final long xorOut; private final boolean reflected; /** * Constructs a {@link CrcParameters} with the given parameters. * * @param name the canonical name of the CRC function * @param bitWidth the width of the CRC function * @param polynomial the polynomial in binary form (non-reflected) * @param initial the initial value of the CRC register * @param xorOut a value XOR'ed with the CRC when it is read * @param reflected indicates whether the CRC is reflected (LSB-first) * @throws IllegalArgumentException if the width is less than 1 or greater * than 64 */ public CrcParameters(String name, int bitWidth, long polynomial, long initial, long xorOut, boolean reflected) { if (bitWidth < 1 || bitWidth > 64) throw new IllegalArgumentException(); this.name = name; this.bitWidth = bitWidth; final long mask = bitWidth < 64 ? (1L << bitWidth) - 1 : ~0L; this.polynomial = polynomial & mask; this.initial = initial & mask; this.xorOut = xorOut & mask; this.reflected = reflected; } @Override public String algorithm() { return name; } /** * Returns the width in bits of the CRC function. The width is also the * position of the implicit set bit at the top of the polynomial. * * @return the CRC width in bits */ public int bitWidth() { return bitWidth; } /** * Returns the binary form of polynomial that defines the CRC function (with * the implicit top bit omitted). For instance, the CRC-16 polynomial * x<sup>16</sup> + x<sup>15</sup> + x<sup>2</sup> + 1 is represented as * {@code 1000 0000 0000 0101} ({@code 0x8005}). * * @return the CRC polynomial */ public long polynomial() { return polynomial; } /** * Returns the initial value of the CRC register. * * @return the CRC initial value */ public long initial() { return initial; } /** * Returns the value XOR'ed with the CRC register when it is read to * determine the output value. * * @return the final XOR value */ public long xorOut() { return xorOut; } /** * Returns whether the CRC function is "reflected". Reflected CRCs process * data LSB-first, whereas "normal" CRCs are MSB-first. * * @return whether the CRC function is reflected */ public boolean reflected() { return reflected; } /** * Returns whether this object matches the given CRC parameters. * * @param bitWidth the width of the CRC function * @param polynomial the polynomial in binary form (non-reflected) * @param initial the initial value of the CRC register * @param xorOut a value XOR'ed with the CRC when it is read * @param reflected indicates whether the CRC is reflected (LSB-first) * @return true if all parameters match exactly, false otherwise */ public boolean match(int bitWidth, long polynomial, long initial, long xorOut, boolean reflected) { return bitWidth == this.bitWidth && polynomial == this.polynomial && initial == this.initial && xorOut == this.xorOut && reflected == this.reflected; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; final CrcParameters other = (CrcParameters) obj; return bitWidth == other.bitWidth && polynomial == other.polynomial && initial == other.initial && xorOut == other.xorOut && reflected == other.reflected; } @Override public int hashCode() { return (int) (polynomial ^ (polynomial >>> 32) ^ initial ^ (initial >>> 32) ^ xorOut ^ (xorOut >>> 32)) ^ (reflected ? ~0 : 0); } /** * Parameters for CRC-16, used in the ARC and LHA compression utilities. */ public static final CrcParameters CRC16 = new CrcParameters("CRC-16", 16, 0x8005, 0, 0, true); /** * Parameters for CRC-16/CCITT, used in the Kermit protocol. */ public static final CrcParameters CRC16_CCITT = new CrcParameters("CRC-16/CCITT", 16, 0x1021, 0, 0, true); /** * Parameters for CRC-16/XMODEM, used in the XMODEM protocol. */ public static final CrcParameters CRC16_XMODEM = new CrcParameters("CRC-16/XMODEM", 16, 0x1021, 0, 0, false); /** * Parameters for CRC-32, used in Ethernet, SATA, PKZIP, ZMODEM, etc. */ public static final CrcParameters CRC32 = new CrcParameters("CRC-32", 32, 0x04c11db7, ~0, ~0, true); /** * Parameters for CRC-32/BZIP2, used in BZIP2. */ public static final CrcParameters CRC32_BZIP2 = new CrcParameters("CRC-32/BZIP2", 32, 0x04c11db7, ~0, ~0, false); /** * Parameters for CRC-32C, used in iSCSI and SCTP. */ public static final CrcParameters CRC32C = new CrcParameters("CRC-32C", 32, 0x1edc6f41, ~0, ~0, true); /** * Parameters for CRC-32/MPEG-2, used in MPEG-2. */ public static final CrcParameters CRC32_MPEG2 = new CrcParameters("CRC-32/MPEG-2", 32, 0x04c11db7, ~0, 0, false); /** * Parameters for CRC-32/POSIX, used in the {@code cksum} utility. */ public static final CrcParameters CRC32_POSIX = new CrcParameters("CRC-32/POSIX", 32, 0x04c11db7, 0, ~0, false); /** * Parameters for CRC-64, used in the ECMA-182 standard for DLT-1 tapes. */ public static final CrcParameters CRC64 = new CrcParameters("CRC-64", 64, 0x42f0e1eba9ea3693L, 0L, 0L, false); /** * Parameters for CRC-64/XZ, used in the {@code .xz} file format. */ public static final CrcParameters CRC64_XZ = new CrcParameters("CRC-64/XZ", 64, 0x42f0e1eba9ea3693L, ~0L, ~0L, true); }