org.nervousync.security.digest.impl.CRCDigestAdapterImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of utils-jdk11 Show documentation
Show all versions of utils-jdk11 Show documentation
Java utility collections, development by Nervousync Studio (NSYC)
/*
* Licensed to the Nervousync Studio (NSYC) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.nervousync.security.digest.impl;
import org.nervousync.exceptions.utils.DataInvalidException;
import org.nervousync.security.api.SecureAdapter;
import org.nervousync.security.config.CRCConfig;
import org.nervousync.exceptions.crypto.CryptoException;
import org.nervousync.utils.RawUtils;
import java.nio.ByteOrder;
import java.util.*;
/**
* Symmetric CRC crypto adapter class
* CRC摘要算法适配器的实现类
*
* @author Steven Wee [email protected]
* @version $Revision: 1.0.0 $ $Date: Jan 13, 2012 13:50:21 $
*/
public final class CRCDigestAdapterImpl extends SecureAdapter {
/**
* CRC configure
* CRC设置
*/
private final CRCConfig crcConfig;
/**
* CRC polynomial
* CRC多项式编码
*/
private final long polynomial;
/**
* CRC initialize value
* CRC初始值
*/
private final long init;
/**
* CRC check value
*/
private final long check;
/**
* CRC mask value
*/
private final long mask;
/**
* CRC result
* CRC计算结果
*/
private long crc;
/**
* Constructor for CRCDigestAdapterImpl
* CRC摘要算法适配器实现类类的构造方法
*
* @param crcConfig CRC configure
* CRC设置
*/
public CRCDigestAdapterImpl(final CRCConfig crcConfig) {
this.crcConfig = crcConfig;
if (this.crcConfig.isRefIn()) {
this.polynomial = reverseBit(this.crcConfig.getPolynomial(), this.crcConfig.getBit());
this.init = reverseBit(this.crcConfig.getInit(), this.crcConfig.getBit());
} else {
this.polynomial = (this.crcConfig.getBit() < 8)
? (this.crcConfig.getPolynomial() << (8 - this.crcConfig.getBit()))
: this.crcConfig.getPolynomial();
this.init = (this.crcConfig.getBit() < 8)
? (this.crcConfig.getInit() << (8 - this.crcConfig.getBit()))
: this.crcConfig.getInit();
}
this.crc = this.init;
if (this.crcConfig.isRefIn()) {
this.check = 0x1L;
} else {
if (this.crcConfig.getBit() <= 8) {
this.check = 0x80;
} else {
this.check = Double.valueOf(Math.pow(2, this.crcConfig.getBit() - 1)).longValue();
}
}
if (this.crcConfig.getBit() <= 8) {
this.mask = 0xFF;
} else {
StringBuilder stringBuilder = new StringBuilder();
while (stringBuilder.length() < this.crcConfig.getBit()) {
stringBuilder.append("1");
}
this.mask = Long.valueOf(stringBuilder.toString(), 2);
}
}
/**
* Append parts of given binary data array to current adapter
* 追加给定的二进制字节数组到当前适配器
*
* @param dataBytes binary data array
* 二进制字节数组
* @param position Data begin position
* 数据起始坐标
* @param length Length of data append
* 追加的数据长度
*
* @throws CryptoException
* If an error occurs when process data
* 当处理数据时出现异常
*/
@Override
public void append(final byte[] dataBytes, final int position, final int length) throws CryptoException {
if (dataBytes.length < (position + length)) {
throw new CryptoException(0x000000150001L, "Length_Not_Enough_Crypto_Error");
}
for (int i = position ; i < length ; i++) {
long crc = (dataBytes[i] < 0) ? ((int)dataBytes[i]) + 256 : dataBytes[i];
if (this.crcConfig.getBit() <= 8) {
this.crc ^= crc;
} else {
this.crc ^= ((this.crcConfig.isRefIn() ? crc : (crc << (this.crcConfig.getBit() - 8))) & this.mask);
}
for (int j = 0; j < 8; j++) {
if ((this.crc & this.check) > 0) {
this.crc = (this.crcConfig.isRefIn() ? (this.crc >>> 1) : (this.crc << 1)) ^ this.polynomial;
} else {
this.crc = this.crcConfig.isRefIn() ? (this.crc >>> 1) : (this.crc << 1);
}
}
}
this.crc &= this.mask;
}
/**
* Append parts of given binary data array to current adapter and calculate final result
* 追加给定的二进制字节数组到当前适配器并计算最终结果
*
* @param dataBytes binary data array
* 二进制字节数组
* @param position Data begin position
* 数据起始坐标
* @param length Length of data append
* 追加的数据长度
*
* @return Calculate result data byte array
* 计算的二进制字节数组结果
*
* @throws CryptoException
* If an error occurs when process data
* 当处理数据时出现异常
*/
@Override
public byte[] finish(final byte[] dataBytes, final int position, final int length) throws CryptoException {
this.append(dataBytes, position, length);
if (this.crcConfig.getBit() < 8 && !this.crcConfig.isRefIn()) {
this.crc >>>= (8 - this.crcConfig.getBit());
}
if (!Objects.equals(this.crcConfig.isRefIn(), this.crcConfig.isRefOut()) && this.crcConfig.isRefOut()) {
// Just using for CRC-12/UMTS
this.crc &= this.mask;
this.crc = (reverseBit(this.crc, Long.toString(this.crc, 2).length()) ^ this.crcConfig.getXorOut());
} else {
this.crc = (this.crc ^ this.crcConfig.getXorOut()) & this.mask;
}
byte[] result = new byte[8];
try {
RawUtils.writeLong(result, ByteOrder.LITTLE_ENDIAN, this.crc);
} catch (DataInvalidException ignore) {
return new byte[0];
}
this.reset();
return result;
}
/**
* Verify given signature data bytes is valid
* 验证给定的签名二进制数据是合法的
*
* @param signature signature data bytes
* 签名二进制数据
*
* @return Verify result
* 验证结果
*/
@Override
public boolean verify(final byte[] signature) {
if (signature == null || signature.length != 8) {
return Boolean.FALSE;
}
try {
return this.crc == RawUtils.readLong(signature, ByteOrder.LITTLE_ENDIAN);
} catch (DataInvalidException ignore) {
return Boolean.FALSE;
}
}
/**
* Reset current adapter
* 重置当前适配器
*/
@Override
public void reset() {
this.crc = this.init;
}
/**
* Reverse result bit
* 反转结果比特位
*
* @param value result value
* 结果值
* @param bit Bit value
* 比特位
*
* @return Reverse bit result
* 反转比特位的结果值
*/
private static long reverseBit(long value, int bit) {
if (value < 0) {
value += Math.pow(2, bit);
}
String reverseValue = new StringBuilder(Long.toString(value, 2)).reverse().toString();
if (reverseValue.length() < bit) {
StringBuilder stringBuilder = new StringBuilder(reverseValue);
while (stringBuilder.length() < bit) {
stringBuilder.append("0");
}
reverseValue = stringBuilder.toString();
} else {
reverseValue = reverseValue.substring(0, bit);
}
return Long.parseLong(reverseValue, 2);
}
}