I wrote a simplified version of SHA256 algorithm and tried some inputs. At first it seems to work fine(although the output is a bit different from the online codes), but when I tried with input "admin", it outputs the same hash regardless of salt String added to input. Surprisingly, if input is "admi", "admin1" or "admin1234", it still outputs the same hash. I didn't find any other input that has the same problem.
Here's the code:
package src.encrypt;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Random;
public class Password {
private String salt;
private String hash;
private String saltGen() {
final String hex = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
Random rnd = new Random(Instant.now().toEpochMilli());
char[] salt = new char[16];
for (int i = 0; i < 16; i++) {
int n = rnd.nextInt(hex.length());
salt[i] = hex.charAt(n);
}
return String.valueOf(salt);
}
public Password() {
};
public Password(String pass) {
salt = saltGen();
String p = new String(pass + salt);
hash = sha256(p);
}
public String getSalt() {
return salt;
}
public String getHash() {
return hash;
}
public boolean compareHash(String h) {
return getHash().equals(sha256(h + getSalt()));
}
// SHA-256 Hashing Algorithm
public String sha256(String str) {
// Pre-processing
ArrayList<String> hash = new ArrayList<>();
byte[] bytes = str.getBytes();
int i = 0;
for (i = 0; i < bytes.length - 4; i += 4) {
String tmp = String.format("%8s", Integer.toBinaryString(bytes[i] & 0xff)).replace(' ', '0')
+ String.format("%8s", Integer.toBinaryString(bytes[i + 1] & 0xff)).replace(' ', '0') +
String.format("%8s", Integer.toBinaryString(bytes[i + 2] & 0xff)).replace(' ', '0') +
String.format("%8s", Integer.toBinaryString(bytes[i + 3] & 0xff)).replace(' ', '0');
hash.add(tmp);
}
String temp = new String();
for (int j = i; j < bytes.length; j++)
temp = new String(temp + String.format("%8s", Integer.toBinaryString(bytes[j] & 0xff)).replace(' ', '0'));
if (temp.length() < 32)
temp = new String(temp + "10000000");
while (temp.length() < 32)
temp = new String(temp + "00000000");
hash.add(temp);
int l = 14 - hash.size() % 16;
for (i = 0; i < l; i++)
hash.add(new String("00000000000000000000000000000000"));
String tmp = String.format("%64s", Long.toBinaryString((long) (bytes.length * 8))).replace(' ', '0');
hash.add(tmp.substring(0, 32));
hash.add(tmp.substring(32));
// Init Hash values
int H[] = {
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
};
// Init Round Constants
int K[] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
// Create Message Schedule and Compressing
l = hash.size() / 16;
int a = H[0], b = H[1], c = H[2], d = H[3], e = H[4], f = H[5], g = H[6], h = H[7];
ArrayList<Integer> w = new ArrayList<>();
for (i = 0; i < l; i++) {
for (int j = i * 16; j < (i + 1) * 16; j++) {
w.add(Integer.parseInt(hash.get(j), 2));
}
for (int j = 16; j < 64; j++) {
int s0 = rightRotate1(w.get(j - 15));
int s1 = rightRotate2(w.get(j - 15));
w.add(w.get(j - 16) + s0 + w.get(j - 7) + s1);
}
for (int j = 0; j < 64; j++) {
int temp1 = h + rightRotate3(e) + ((e & f) ^ (~e & g)) + K[i] + w.get(i);
int temp2 = rightRotate4(a) + ((a & b) ^ (a & c) ^ (b & c));
h = g;
g = f;
f = e;
e = d + temp1;
d = c;
c = b;
b = a;
a = temp1 + temp2;
}
// Modify final values
H[0] = H[0] + a;
H[1] = H[1] + b;
H[2] = H[2] + c;
H[3] = H[3] + d;
H[4] = H[4] + e;
H[5] = H[5] + f;
H[6] = H[6] + g;
H[7] = H[7] + h;
}
// Concatenate final hash
String s = new String();
for (i = 0; i < 8; i++) {
s = new String(s + String.format("%08X", H[i]).toLowerCase());
}
return s;
};
// right rotate
private int rotr(int x, int n) {
return (x >>> n) | (x << (32 - n));
}
private int rightRotate3(int x) {
return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25);
}
private int rightRotate4(int x) {
return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22);
}
private int rightRotate1(int x) {
return rotr(x, 7) ^ rotr(x, 18) ^ x >>> 3;
}
private int rightRotate2(int x) {
return rotr(x, 17) ^ rotr(x, 19) ^ x >>> 10;
}
With input "admin", output is always "0920b401857e70a28c7b645c04195f2f15b54b98a7e7810f6d46c3a9c74adf6a"
Can anyone spot some bugs or mistakes that I made?
Please note that I'm new to Java so some methods I use maybe unefficient.
EDIT
Here's how I call the method:
// Main.java
import src.encrypt.Password;
public class Main {
public static void main(String[] args) {
String pass = "admin";
Password p = new Password(pass);
System.out.println(p.getSalt()); // different calls, different values
System.out.println(p.getHash()); // different calls, same value
}
}
The error occurs in the processing of the message schedule array (the w arraylist, the terminology is from https://en.wikipedia.org/wiki/SHA-2):
for (int j = 0; j < 64; j++) {
int temp1 = h + rightRotate3(e) + ((e & f) ^ (~e & g)) + K[i] + w.get(i);
int temp2 = rightRotate4(a) + ((a & b) ^ (a & c) ^ (b & c));
h = g;
g = f;
f = e;
e = d + temp1;
d = c;
c = b;
b = a;
a = temp1 + temp2;
}
Your loop variable here is j, but you use the variable i to access the message schedule array (i is used in the outer loop that processes the message chunks).
The correct code is
for (int j = 0; j < 64; j++) {
int temp1 = h + rightRotate3(e) + ((e & f) ^ (~e & g)) + K[j] + w.get(j);
int temp2 = rightRotate4(a) + ((a & b) ^ (a & c) ^ (b & c));
h = g;
g = f;
f = e;
e = d + temp1;
d = c;
c = b;
b = a;
a = temp1 + temp2;
}
Related
I am trying to implement the SHA-1 algorithm in Java 11, and while testing the hashing algorithm I get different hashes than when hashing with the java.security implementation of SHA-1.
The pseudocode I attempted to follow can be found on Wikipedia.
public static byte[] hash(byte[] message) {
int h0 = 0x67452301;
int h1 = 0xEFCDAB89;
int h2 = 0x98BADCFE;
int h3 = 0x10325476;
int h4 = 0xC3D2E1F0;
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.writeBytes(message);
out.write(0x00000080);
while (out.size() % 64 != 56) out.write(0x00000000);
out.writeBytes(ByteBuffer.allocate(8).putLong(message.length).array());
byte[] data = out.toByteArray();
for (int j = 0; j < data.length / 64; ++j) {
int[] w = new int[80];
for (int i = 0; i < 16; ++i) {
w[i] = ByteBuffer.wrap(data, j * 64 + i * 4, 4).getInt();
}
for (int i = 16; i < 80; ++i) {
w[i] = leftrotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1);
}
int a = h0;
int b = h1;
int c = h2;
int d = h3;
int e = h4;
for (int i = 0; i < 80; ++i) {
final int f, k;
if (i < 20) {
f = (b & c) | ((~b) & d);
k = 0x5A827999;
} else if (i < 40) {
f = b ^ c ^ d;
k = 0x6ED9EBA1;
} else if (i < 60) {
f = (b & c) | (b & d) | (c & d);
k = 0x8F1BBCDC;
} else {
f = b ^ c ^ d;
k = 0xCA62C1D6;
}
int t = leftrotate(a, 5) + f + e + k + w[i];
e = d;
d = c;
c = leftrotate(b, 30);
b = a;
a = t;
}
h0 += a;
h1 += b;
h2 += c;
h3 += d;
h4 += e;
}
ByteBuffer buffer = ByteBuffer.allocate(20);
buffer.putInt(h0);
buffer.putInt(h1);
buffer.putInt(h2);
buffer.putInt(h3);
buffer.putInt(h4);
return buffer.array();
}
public static int leftrotate(int x, int c) {
return (x << c) | (x >> (32 - c));
}
To test this out, I attempt to hash a random array of n bytes, and compare the hash to the one obtained by
MessageDigest.getInstance("SHA-1").digest(message)
I get different hashes.
Is there any mistake in my implementation above? Could the error come from somewhere else?
There were two problems with the implementation. First, I was writing the size of the initial message in bytes and not in bits. Second, the leftrotate method was using the arithmetic right shift when it should have been using the logical right shift.
I am trying to find the maximum product of two non overlapping palindromic sub-sequences of string s that we'll refer to as a and b. I came up with below code but it's not giving correct output:
public static int max(String s) {
int[][] dp = new int[s.length()][s.length()];
for (int i = s.length() - 1; i >= 0; i--) {
dp[i][i] = 1;
for (int j = i+1; j < s.length(); j++) {
if (s.charAt(i) == s.charAt(j)) {
dp[i][j] = dp[i+1][j-1] + 2;
} else {
dp[i][j] = Math.max(dp[i+1][j], dp[i][j-1]);
}
}
}
return dp[0][s.length()-1];
}
For input string "acdapmpomp", we can choose a = "aca" and b ="pmpmp" to get a maximal product of score 3 * 5 = 15. But my program gives output as 5.
Firstly you should traverse the dp table to find out the length of longest palindromic subsequences using bottom up approach, then you can calculate the max product by multiplying dp[i][j] with dp[j+1][n-1] : Given below is the code in C++;
int longestPalindromicSubsequenceProduct(string x){
int n = x.size();
vector<vector<int>> dp(n,vector<int>(n,0));
for(int i=0;i<n;i++){
dp[i][i] = 1;
}
for(int k=1;k<n;k++){
for(int i=0;i<n-k;i++){
int j = i + k;
if(x[i]==x[j]){
dp[i][j] = 2 + dp[i+1][j-1];
} else{
dp[i][j] = max(dp[i][j-1],dp[i+1][j]);
}
}
}
int maxProd = 0;
for(int i=0;i<n;i++){
for(int j=0;j<n-1;j++){
maxProd = max(maxProd,dp[i][j]*dp[j+1][n-1]);
}
}
return maxProd;
}
int multiplyPalindrome(string s) {
int n=s.size(),m=0;
vector<vector<int>> dp(n, vector<int> (n));
for(int i=0;i<n;i++) dp[i][i]=1;
for (int cl=2; cl<=n; cl++) {
for (int i=0; i<n-cl+1; i++){
int j = i+cl-1;
if (s[i] == s[j] && cl == 2) dp[i][j] = 2;
else if (s[i] == s[j]) dp[i][j] = dp[i+1][j-1] + 2;
else dp[i][j] = max(dp[i][j-1], dp[i+1][j]);
}
}
for(int i=0;i<n-1;i++){
m = max( m, dp[0][i]*dp[i+1][n-1] );
}
return m;
}
int palSize(string &s, int mask) {
int p1 = 0, p2 = s.size(), res = 0;
while (p1 <= p2) {
if ((mask & (1 << p1)) == 0)
++p1;
else if ((mask & (1 << p2)) == 0)
--p2;
else if (s[p1] != s[p2])
return 0;
else
res += 1 + (p1++ != p2--);
}
return res;
}
int maxProduct(string s) {
int mask[4096] = {}, res = 0;
for (int m = 1; m < (1 << s.size()); ++m)
mask[m] = palSize(s, m);
for (int m1 = 1; m1 < (1 << s.size()); ++m1)
if (mask[m1])
for (int m2 = 1; m2 < (1 << s.size()); ++m2)
if ((m1 & m2) == 0)
res = max(res, mask[m1] * mask[m2]);
return res;
}
You can loop through all non-overlapping palindromic subsequences and return the maximum value.
public int longestPalindromicSubsequenceProduct(String str) {
int maxProduct = 0;
for (int k = 0; k < str.length(); k++) {
String left = str.substring(0, k);
String right = str.substring(k);
int currProduct = longestPalindromicSubsequence(left) * longestPalindromicSubsequence(right);
maxProduct = Math.max(maxProduct, currProduct);
}
return maxProduct;
}
private int longestPalindromicSubsequence(String org) {
String rev = new StringBuilder(org).reverse().toString();
return longestCommonSubsequence(org, rev);
}
private int longestCommonSubsequence(String str1, String str2) {
int rows = str1.length();
int cols = str2.length();
int[][] dp = new int[rows + 1][cols + 1];
for (int r = 1; r <= rows; r++) {
for (int c = 1; c <= cols; c++) {
if (str1.charAt(r - 1) == str2.charAt(c - 1)) dp[r][c] = 1 + dp[r - 1][c - 1];
else dp[r][c] = Math.max(dp[r - 1][c], dp[r][c - 1]);
}
}
return dp[rows][cols];
}
Your algorithm returns the maximum length of a palyndrome, not the maximum of the product of two lengths.
UPDATE
Here's a possible solution:
public static int max(String s) {
int max = 0;
for (int i = 1; i < s.length()-1; ++i) {
String p1 = bestPalyndrome(s, 0, i);
String p2 = bestPalyndrome(s, i, s.length());
int prod = p1.length()*p2.length();
if (prod > max) {
System.out.println(p1 + " " + p2 + " -> " + prod);
max = prod;
}
}
return max;
}
private static String bestPalyndrome(String s, int start, int end) {
if (start >= end) {
return "";
} else if (end-start == 1) {
return s.substring(start, end);
} else if (s.charAt(start) == s.charAt(end-1)) {
return s.charAt(start) + bestPalyndrome(s, start+1, end-1)
+ s.charAt(end-1);
} else {
String s1 = bestPalyndrome(s, start, end-1);
String s2 = bestPalyndrome(s, start+1, end);
return s2.length() > s1.length() ? s2 : s1;
}
}
import java.io.*;
static int MOD = 1000000007;
public class power {
public static long power(long num, int p) {
if (p == 0) return 1;
if (p == 1) return num;
long number = num;
for (int i = 2; i <= p; i++) {
num *= number;
num %= MOD;
}
return num;
}
};
public class Solution {
public static void main(String[] args) throws Exception {
int N, M;
long[] T = new long[1001];
long[] S = new long[1001];
long[] P = new long[1001];
T[0] = T[1] = 1;
T[2] = 2;
T[3] = 4;
T[4] = 8;
P[0] = P[1] = 1;
for (int i = 5; i <= 1000; i++)
T[i] = (T[i - 1] + T[i - 2] + T[i - 3] + T[i - 4]) % MOD;
S[0] = 1;
S[1] = 1;
long sum;
int Tt;
BufferedReader br = new BufferedReader(new InputStreamReader(System. in ));
String line = br.readLine();
Tt = Integer.parseInt(line);
for (int t = 0; t < Tt; t++) {
line = br.readLine();
String[] inputStr = line.split(" ");
N = Integer.parseInt(inputStr[0]);
M = Integer.parseInt(inputStr[1]);
power p = new power();
for (int i = 0; i <= M; i++)
P[i] = p.power(T[i], N);
for (int i = 2; i <= M; i++) {
sum = 0;
for (int j = 1; j < i; j++) {
sum += (S[j] * P[i - j]) % MOD;
sum %= MOD1;
}
S[i] = (P[i] - sum);
S[i] = S[i] % MOD;
}
while (S[M] < 0)
S[M] += MOD;
System.out.println(S[M]);
}
}
}
On compilation, it gives an error that,
class,interface, or enum expected
static int MOD = 100000007;
Why is it so? Also, is their any other error that can lead to compilation error? How can I correct it? I am new to Java. I don't understand why is their a error in the first place.
static int MOD = 1000000007;
written out side class.
Include it inside class power then use power.MOD
Code should be :
public class power {
static int MOD = 1000000007;
//rest of your code
}
The declaration of the field must be inside of the class:
Change to :
public class power {
static int MOD = 1000000007;
Declare static int MOD = 1000000007; inside the power class and import package to access from main method.
import static com.regex.power.MOD;
public class power {
static int MOD = 1000000007;
Declare it this way
public class power {
public static int MOD = 1000000007;
And you can access it through class name in your main method.
power.MOD
Note:
You should not have method name as your class name (in your case power).
I have removed all compilation error. Added comments for the changes which I have done.
public class Power {
public static int MOD = 1000000007;
public static long findPower(long num, int p) { // changed method name as it was same as class name
if (p == 0)
return 1;
if (p == 1)
return num;
long number = num;
for (int i = 2; i <= p; i++) {
num *= number;
num %= MOD;
}
return num;
}
}
class Solution { // removed public. If you want to use public then you will have to create another java file name Solution.java and paste Solution class code inside that java file.
public static void main(String[] args) throws Exception {
int N, M;
long[] T = new long[1001];
long[] S = new long[1001];
long[] P = new long[1001];
T[0] = T[1] = 1;
T[2] = 2;
T[3] = 4;
T[4] = 8;
P[0] = P[1] = 1;
for (int i = 5; i <= 1000; i++)
T[i] = (T[i - 1] + T[i - 2] + T[i - 3] + T[i - 4]) % Power.MOD; // access using Power.MOD
S[0] = 1;
S[1] = 1;
long sum;
int Tt;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
Tt = Integer.parseInt(line);
for (int t = 0; t < Tt; t++) {
line = br.readLine();
String[] inputStr = line.split(" ");
N = Integer.parseInt(inputStr[0]);
M = Integer.parseInt(inputStr[1]);
// Power p = new Power();
for (int i = 0; i <= M; i++)
P[i] = Power.findPower(T[i], N); // No need to use object, you can directly access static methods using class
for (int i = 2; i <= M; i++) {
sum = 0;
for (int j = 1; j < i; j++) {
sum += (S[j] * P[i - j]) % Power.MOD;
sum %= Power.MOD;
}
S[i] = (P[i] - sum);
S[i] = S[i] % Power.MOD;
}
while (S[M] < 0)
S[M] += Power.MOD;
System.out.println(S[M]);
}
}
}
I need some help on a program i'm supposed to create. i'm supposed to create a program that reads two strings of any length that are user inputted and it subtracts or adds them together. i'm NOT allowed to convert these strings into numbers before the operation. this is what I got so far.My teacher mentioned something like converting the strings into uni-code to add and subtract them but i have no idea how to do it as we haven't even learned uni-code. HERE IS MY CODE:
import java.util.Scanner;
public class Number {
private char Sign;
private String Whole;
private String Fraction;
public static void main(String[] args) {
Scanner Keyboard = new Scanner (System.in);
System.out.println("This program adds or subtracts numbers of any lengths, please add two numbers: ");
String num1 = Keyboard.nextLine();
System.out.println("Enter the second number: ");
String num2 = Keyboard.nextLine();
String sum = " ";
int length = num1.length();
int carry = 0;
public Number Add(Number RHS) {
for (int i = length -1 ; i >= 0; i--) {
char c1 = num1.charAt(i);
char c2 = num2.charAt(i);
int tempSum = (c1 - 48) + (c2 - 48) + carry;
carry = tempSum / 10;
int sumDigit = tempSum % 10;
sum = (char) (sumDigit + 48) + sum;
if (carry == 1) {
sum = "1" + sum;
}
}
}
}
public Number (double n) {
Whole = " ";
Fraction = " ";
if (n >= 0) {
Sign = '+';
}
else
{
Sign = '-';
n = Math.abs(n);
String numString = new Double(n).toString();
int position = numString.indexOf(".");
}
}
}
public static String add(String as, String bs){
ArrayList<String> BigNum = new ArrayList<>();
int m = as.length()-1;
int n = bs.length()-1;
int min = m > n ? n : m ;
int max = 0;
String s;
if(n > m){
s = bs;
max = n;
}else{s = as ; max = m;}
Integer carry = 0;
while(true){
int a = Integer.parseInt(Character.toString(as.charAt(m)));
int b = Integer.parseInt(Character.toString(bs.charAt(n)));
Integer c = a + b + carry;
if(c > 9){
carry = 1;
c %=10;
}else carry = 0;
BigNum.add(c.toString());
n--; m--; min--; max--;
if ( min < 0 ) {
if(carry !=0 && max < 0 )
BigNum.add(carry.toString());
break;
}
}
Integer c = carry;
while(max >= 0) {
c += Integer.parseInt(Character.toString(s.charAt(max)));
BigNum.add(c.toString());
c = 0;
max--;
}
String s2 = "";
for (int i = BigNum.size()-1; i >= 0; i--) {
s2 +=BigNum.get(i);
}
return s2;
}
I need help with calculating of CCITT standard CRC with polynomial x^16 + x^12 + x^5 + 1 (0x1081) in Java. I have tried many examples on the internet but every one of them returns other values than the ones in the example.
For example for this array [0xFC] [05] [11] the result needs to be [27] [56].
Using this code:
public static void main(String[] args) {
byte[] array = new byte[3];
array[0] = (byte) 0xFC;
array[1] = (byte) 0x05;
array[2] = (byte) 0x11;
// array[3] = (byte) 0x00;
// array[4] = (byte) 0x00;
System.out.println(Integer.toHexString(crc16(array)));
}
private static final int POLYNOMIAL = 0x1081;
private static final int PRESET_VALUE = 0xFFFF;
public static int crc16(byte[] data) {
int current_crc_value = PRESET_VALUE;
for (int i = 0; i < data.length; i++) {
current_crc_value ^= data[i] & 0xFF;
for (int j = 0; j < 8; j++) {
if ((current_crc_value & 1) != 0) {
current_crc_value = (current_crc_value >>> 1) ^ POLYNOMIAL;
} else {
current_crc_value = current_crc_value >>> 1;
}
}
}
current_crc_value = ~current_crc_value;
return current_crc_value & 0xFFFF;
}
I get result FA DE not [27] [56]
Using this code:
public static void main(String[] args) {
int crc = 0x0000;
int polynomial = 0x1081;
// byte[] testBytes = "123456789".getBytes("ASCII");
// byte[] array = args[0].getBytes();
byte[] array = new byte[3];
array[0] = (byte) 0xFC;
array[1] = (byte) 0x05;
array[2] = (byte) 0x11;
for (byte b : array) {
for (int i = 0; i < 8; i++) {
boolean bit = ((b >> (7-i) & 1) == 1);
boolean c15 = ((crc >> 15 & 1) == 1);
crc <<= 1;
if (c15 ^ bit) crc ^= polynomial;
}
}
crc &= 0xffff;
System.out.println("CRC16-CCITT = " + Integer.toHexString(crc));
}
I get this CRC16-CCITT = 8dca
Using this code:
private final int polynomial = 0x1081;
private int[] table = new int[256];
public int ComputeChecksum(int[] bytes) {
int crc = 0xffff;
for (int i = 0; i < bytes.length; ++i) {
int index = (crc ^ bytes[i]) % 256;
crc = (crc >> 8) ^ table[index];
}
return crc;
}
public CRC162() {
int value;
int temp;
for (int i = 0; i < table.length; ++i) {
value = 0;
temp = i;
for (byte j = 0; j < 8; ++j) {
if (((value ^ temp) & 0x0001) != 0) {
value = (value >> 1) ^ polynomial;
} else {
value >>= 1;
}
temp >>= 1;
}
table[i] = value;
}
}
public static void main(String[] args) {
CRC162 c = new CRC162();
int[] arr = new int[]{0xFC, 0x05, 0x11};
System.out.println(Integer.toHexString(c.ComputeChecksum(arr)));
}
I get this 521
Hope someone can help me. I need this for communication with device using ID003 protocol.
EDIT:
Using this online calculator at http://www.lammertbies.nl/comm/info/crc-calculation.html for input FC0511 i get 0x2756 right from CRC-CCITT (Kermit).
x^16 + x^12 + x^5 + 1 is not 0x1081. It is 0x1021. x^5 is 20, not 80. (Note that the x^16 is dropped.)
Furthermore, the Kermit CRC that you need is reflected, so the polynomial is reversed giving 0x8408.
For this CRC, you initialize with zero and do not complement the result.
So modifying your first example accordingly, this computes what you want:
public static void main(String[] args) {
byte[] array = new byte[3];
array[0] = (byte) 0xFC;
array[1] = (byte) 0x05;
array[2] = (byte) 0x11;
// array[3] = (byte) 0x00;
// array[4] = (byte) 0x00;
System.out.println(Integer.toHexString(crc16(array)));
}
private static final int POLYNOMIAL = 0x8408;
private static final int PRESET_VALUE = 0;
public static int crc16(byte[] data) {
int current_crc_value = PRESET_VALUE;
for (int i = 0; i < data.length; i++) {
current_crc_value ^= data[i] & 0xFF;
for (int j = 0; j < 8; j++) {
if ((current_crc_value & 1) != 0) {
current_crc_value = (current_crc_value >>> 1) ^ POLYNOMIAL;
} else {
current_crc_value = current_crc_value >>> 1;
}
}
}
return current_crc_value & 0xFFFF;
}
Here is another version of the Kermit CRC. This one is a direct translation from the C codes in http://www.lammertbies.nl/comm/info/crc-calculation.html. The optimisation is that a table of CRC value for any byte is pre-computed at class loading time, and so the remaining of CRC computations is much simpler.
public class Crc {
private static final int POLYNOMIAL = 0x8408;
private static final int PRESET = 0;
static private int[] tab;
static {
tab = new int[256];
for (int i = 0; i < 256; i++) {
tab[i] = initial((byte) i);
}
}
private static int initial(byte c) {
int crc = 0;
for (int j = 0; j < 8; j++) {
if (((crc ^ c) & 1) == 1) {
crc = ((crc >> 1) ^ POLYNOMIAL);
} else {
crc = (crc >> 1);
}
c = (byte) (c >> 1);
}
return crc;
}
private static int update_crc(int crc, byte c) {
int cc = (0xff & c);
int tmp = (crc ^ cc);
crc = (crc >> 8) ^ tab[tmp & 0xff];
return crc;
}
private static int swab(int n) {
return (((n & 0xFF00) >> 8) + ((n & 0xFF) << 8));
}
public static int crc(String str) {
return crcb(str.getBytes());
}
public static int crcb(byte... i) {
int crc = PRESET;
for (byte c : i) {
crc = update_crc(crc, c);
}
return swab(crc);
}
public static void main(String[] args) {
int crc = Crc.crcb((byte) 0xFC, (byte) 5, (byte) 0x11);
System.out.println(Integer.toHexString(crc));
crc = Crc.crc("123456789");
System.out.println(Integer.toHexString(crc));
}
}
The output is as expected :
2756
8921
This is not mine but worked perfect for me, "DatatypeConverter" is something i already have in my proyect. This is a real world example for me and works.
* Reads in a sequence of bytes and prints out its 16 bit
* Cylcic Redundancy Check (CRC-CCIIT 0xFFFF).
*
* 1 + x + x^5 + x^12 + x^16 is irreducible polynomial.
import javax.xml.bind.DatatypeConverter;
public class CRC16CCITT {
public static void main(String[] args) {
int crc = 0xFFFF; // initial value
int polynomial = 0x1021; // 0001 0000 0010 0001 (0, 5, 12), in your case: 0x1081
// CRC of this should be 28570
byte[] testBytes = DatatypeConverter.parseHexBinary("00000000000000000000FA00000002009F1D19B87475445E1122330000000000");
for (byte b : testBytes) {
for (int i = 0; i < 8; i++) {
boolean bit = ((b >> (7 - i) & 1) == 1);
boolean c15 = ((crc >> 15 & 1) == 1);
crc <<= 1;
if (c15 ^ bit)
crc ^= polynomial;
}
}
crc &= 0xffff;
System.out.println("CRC16-CCITT = " + Integer.toHexString(crc));
// 6F9A = 28570
}
}
/**
* converts the given String to CRC16
*
* #param inputStr
* - the input string to get the CRC
* #param polynomial
* - the polynomial (divisor)
* #param crc
* - the CRC mask
* #param isHex
* - if true, treat input string as hex, otherwise, treat as
* ASCII
* #return
*/
public static String getCRC16CCITT(String inputStr, int polynomial,
int crc, boolean isHex) {
int strLen = inputStr.length();
int[] intArray;
if (isHex) {
if (strLen % 2 != 0) {
inputStr = inputStr.substring(0, strLen - 1) + "0"
+ inputStr.substring(strLen - 1, strLen);
strLen++;
}
intArray = new int[strLen / 2];
int ctr = 0;
for (int n = 0; n < strLen; n += 2) {
intArray[ctr] = Integer.valueOf(inputStr.substring(n, n + 2), 16);
ctr++;
}
} else {
intArray = new int[inputStr.getBytes().length];
int ctr=0;
for(byte b : inputStr.getBytes()){
intArray[ctr] = b;
ctr++;
}
}
// main code for computing the 16-bit CRC-CCITT
for (int b : intArray) {
for (int i = 0; i < 8; i++) {
boolean bit = ((b >> (7 - i) & 1) == 1);
boolean c15 = ((crc >> 15 & 1) == 1);
crc <<= 1;
if (c15 ^ bit)
crc ^= polynomial;
}
}
crc &= 0xFFFF;
return Integer.toHexString(crc).toUpperCase();
}
Works for both ASCII and HEX computation.
public static void main(String args[]) {
String testStr = "9142656";
// XModem ASCII
System.out.println("CRC-CCITT (XModem) Ascii: "
+ getCRC16CCITT(testStr, 0x1021, 0x0000, false));
// 0xFFFF ASCII
System.out.println("CRC-CCITT (0xFFFF) Ascii: "
+ getCRC16CCITT(testStr, 0x1021, 0xFFFF, false));
// 0x1D0F ASCII
System.out.println("CRC-CCITT (0x1D0F) Ascii: "
+ getCRC16CCITT(testStr, 0x1021, 0x1D0F, false));
// XModem Hex
System.out.println("CRC-CCITT (XModem) Hex: "
+ getCRC16CCITT(testStr, 0x1021, 0x0000, true));
// 0xFFFF Hex
System.out.println("CRC-CCITT (0xFFFF) Hex: "
+ getCRC16CCITT(testStr, 0x1021, 0xFFFF, true));
// 0x1D0F Hex
System.out.println("CRC-CCITT (0x1D0F) Hex: "
+ getCRC16CCITT(testStr, 0x1021, 0x1D0F, true));
}
Output:
CRC-CCITT (XModem) Ascii: 87F4
CRC-CCITT (0xFFFF) Ascii: 763A
CRC-CCITT (0x1D0F) Ascii: 9F86
CRC-CCITT (XModem) Hex: 57FF
CRC-CCITT (0xFFFF) Hex: D33F
CRC-CCITT (0x1D0F) Hex: 59EF
Solution is based from the sample found in princeton university http://introcs.cs.princeton.edu/java/61data/CRC16CCITT.java