I have a routine for checksum calculation and it fails for string which have accented characters, to handle accented characters I convert the string to a byte array using the encoding which the string is actually from, for ex: a string will contains accented characters appearing as François^Frédérique^ and the encoding it uses is 'CP437', and if after doing such the checksum calculation fails, thus can you let me know if there is something more I need to be doing.
byte[] frameArray = frame.getBytes(m_fileEncoding);
int frameLength = frameArray.length;
int idx =0;
while (idx < frameLength )
{
int c = frameArray[idx];
sum1 += c;
if (sum1 >= 256)
{
sum1 -= 256;
}
idx++;
}
sum1 = 256 - sum1;
calculatedChecksum = Integer.toHexString(sum1 & 0xff).toUpperCase();
Related
I'm trying to write an algorithm which adds two numbers that are stored as chars in two arrays. Unfortunately, it doesn't work. When I try to debug it, I see that the variables a and b get the value -1 which makes no sense. Any idea what might be the problem?
public class rechner2 {
public static void main(String[] args) {
final char[] zahl1 = {1, 2, 3};
final char[] zahl2 = {7, 8, 9};
//Add arrays zahl1 and zahl2.
char [] zwischenarray = add(zahl1, zahl2);
for (int i = 0; i < zwischenarray.length; i++) {
System.out.println(zwischenarray[i]);
}
}
private static char[] add(char[] zahl1, char[] zahl2) {
int len;
if (zahl1.length < zahl2.length) {
len = zahl2.length;
} else {
len = zahl1.length;
}
char[] finalresult = new char [len + 1];
int carryover = 0;
for (int i = 0; i < len; i++) {
int a = Character.getNumericValue(zahl1[i]);
int b = Character.getNumericValue(zahl2[i]);
int c = a + b + carryover;
if (c > 9) {
carryover = 1;
c = c - 10;
} else {
carryover = 0;
}
finalresult[i] = (char)c;
}
if (carryover == 1) {
finalresult[len + 1] = 1;
}
return finalresult;
}
}
in this code I believe 2 bug
instead of char , i guess better to us int
length of the array
here is the code:
public class rechner2 {
public static void main(String[] args) {
int[] zahl1 = {1,2,3};
int[] zahl2 = {7,8,9};
//Add arrays zahl1 and zahl2.
int [] zwischenarray = add(zahl1, zahl2);
for (int i = 0; i < zwischenarray.length; i++) {
System.out.println(zwischenarray[i]);
}
}
private static int[] add(int[] zahl1, int[] zahl2) {
int len;
if (zahl1.length < zahl2.length) {
len = zahl2.length;
} else {
len = zahl1.length;
}
int[] finalresult = new int [len + 1];
int carryover = 0;
for (int i = 0; i <= len-1; i++) {
int a = (zahl1[i]);
int b = (zahl2[i]);
int c = a + b + carryover;
if (c > 9) {
carryover = 1;
c = c - 10;
} else {
carryover = 0;
}
finalresult[i] = c;
}
if (carryover == 1) {
finalresult[len] = 1;
}
return finalresult;
}
}
Your code is conflicted: The numbers / characters in your array are actually integers, not "printable" or "human readable" characters. But, parts of your code are treating them as if they are "printable".
Let's go back decades, and use ASCII for the beginning of this explanation. ASCII has "Printable" and "Nonprintable" characters. The "Nonprintable" characters are known as "Control codes."
Control codes include codes that move the cursor on a display terminal or print head on a printing terminal. They include thing like CR (Carriage Return), LF (Line Feed), HT (Horizontal tab), and BS (Backspace). Others are used by data communications hardware to control the flow of data, or to report status.
Printable characters correspond to what you see on a terminal screen or printout. They include uppercase alphabetic, lower case alphabetic, digits, punctuation, and the space character. They are "human readable."
Look at the list of printable characters in the Wikipedia article. Take 5 as an example. It's represented as '53' in base ten, which corresponds to '35' in base sixteen, or '011 0101' in binary. Note that it is not the same as the binary number five, which would be '0000 0101'.
Java uses 16 bit Unicode, not ASCII, for its char type. The Java compiler allows arithmetic to be done on char data, as if it was the same as short.
These lines in your code expect your char variables and constants are printable characters:
int a = Character.getNumericValue(zahl1[i]);
int b = Character.getNumericValue(zahl2[i]);
In addition, that you specified zwischenarray as char tells the compiler to handle the contents as printable characters in this line:
System.out.println(zwischenarray[i]);
But, the rest of your code treats your char data as integer data types.
You have a bug in this line: finalresult[len + 1] = 1;. After that bug is fixed, how do you fix the rest of your code? There are different ways, and which is best depends on your intention.
For demonstration purpose, try this: Replace the following
int a = Character.getNumericValue(zahl1[i]);
int b = Character.getNumericValue(zahl2[i]);
int c = a + b + carryover;
with
int c = zahl1[i] + zahl2 [i] + carryover;
Also, put a cast in your output line:
System.out.println((short)zwischenarray[i]);
And run it. That will demonstrate you can do arithmetic on Java char data.
Now, remove the (short) cast in output line, and change all occurrences of char to short (or int). Your program still works.
This is because of the way you entered the values for zahl1 and zahl2. Your source code consists of printable characters and white space. By omitting the single quotes, you told the compiler to convert the values to binary integers. For example, your source code 9 became binary 0000 1001 in the runtime code. If you wanted your 9 to remain as a printable character, you needed to enclose it in single quote marks: '9' .
By enclosing all the values in zahl1 and zahl2 in single quote marks, the use of Character.getNumericValue is appropriate. But, you would still need the (short) or (int) cast in your System.out. line to see your output.
Character.getNumericValue is returning -1 because the values passed are outside of the range it was designed to work with.
Here are two ways to convert a base 10 digit represented as a binary integer to the equivalent printable character:
finalresult[i] = (char) (c + '0');
But, my preference is for this:
final String digit = "0123456789";
finalresult[i] = digit.charAt (c);
I'm completely new to programming and have been tasked with writing a method in Java to decrypt a message encrypted using a Caesar Cipher (without importing any utilities).
The following code was provided for encrypting a message:
public String encrypt(String plainText, int offset) {
String cipher = "";
char[] arr = plainText.toCharArray();
for (int i = 0; i < arr.length; i++) {
int numericalVal = (int) arr[i];
if (Character.isUpperCase(arr[i])) {
cipher += (char) (((numericalVal + offset - 65) % 26) + 65);
} else if (numericalVal == 32) {
cipher += arr[i];
}
else {
cipher += (char) (((numericalVal + offset - 97) % 26) + 97);
}
}
return cipher;
My solution must begin with the line Public String decrypt(String plainText, int offset) {
This is how I attempted to solve the problem:
public String decrypt(String plainText, int offset) {
String decipher = "";
char[] d_arr = plainText.toCharArray();
for (int i = 0; i < d_arr.length; i++) {
int numericalVal = (int) d_arr[i];
if (Character.isUpperCase(d_arr[i])) {
decipher += (char) ((((numericalVal - offset - 65) % 26 + 26) % 26) + 65);
//to get remainder for negative values too
} else if (numericalVal == 32) {
decipher += d_arr[i];
}
else {
decipher += (char) ((((numericalVal - offset - 97) % 26 + 26) % 26) + 97);
}
}
return decipher;
This works when decrypting letters of the alphabet, but non-alphabetical letters are not decrypted properly and I am unsure what the issue is.
For example:
public static void main(String[] args) {
CaesarCipher C = new CaesarCipher();
System.out.println(C.encrypt("?", 4)); //returns the ] symbol
System.out.println(C.decrypt("]", 4)); //returns the letter s
We were told that adjusting the code to ignore non-alphabetical characters entirely was possible but would require more work, so I changed the } else if (numericalVal == 32) { cipher += arr[i]; code in both the encrypt and decrypt Strings to } else if (numericalVal < 65 || (numericalVal > 90 && numericalVal < 97) || numericalVal > 122) { cipher += arr[i];.
This circumvented the issue but I was told that it's much easier to just decrypt the non-alphabetical characters as well, so I reverted this change, but now I'm at a complete loss as to how to solve this problem. I feel like I'm missing something very simple as I managed to do it "the hard way" but cannot do it the easier way. I can see that when a non-alphabetical value is encrypted, the alphabetical letters are essentially skipped, but the same is not occurring for the decryption process. I presume this is related to the adjustment I made to find the remainder of negative values, but I am unsure.
What you generally try and do is to define your own alphabet rather than using the ABC, and put that in a string (or a char array). Then you replace the - 65 (which is not very great when it comes to encoding, you could have used e.g. just - 'A') by looking up the character in the alphabet.
Then you can perform the modulus operation on the size of the alphabet, i.e. alphabet.length() for strings or alphabet.length for char arrays. Then you perform the modular addition / subtraction, and finally you find the corresponding character in your alphabet again.
Now you have some special code for space and upper / lowercase. That would not work anymore when you'd include special characters. There are two ways around this. The simplest one is to create one big alphabet with uppercase, lowercase and special characters. If you want to keep the case you could also use e.g. 3 separate alphabets.
So you start off with e.g.
private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz,.;";
or you could use:
private static final String ALPHABET_UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final String ALPHABET_LOWER = "abcdefghijklmnopqrstuvwxyz";
private static final String ALPHABET_SIGNS = ",.;";
I'd say the single alphabet is a bit more secure as you would directly be able to see the signs in the other. Then again, the Caesar cipher was only somewhat secure when almost nobody was able to read in the first place.
Better split your application into methods, have at least:
charToIndex(char c): int;
indexToChar(int i): char;
shiftIndex(int i, int shift): int.
and while we are at it:
public static int mod(int i, int n) {
return ((i % n) + n) % n;
}
I have written both encryption and decryption methods to be able to encrypt plain text or decrypt cipher text. I am unsure how to successfully implement this, however, due to taking in the HEX and text as a STRING and unsure how to convert them to int arrays, and then how to successfully print the result out without it being a bunch of jumbled letters. What am I doing incorrectly?
The following code is the two TEA methods for either encryption or decryption:
public void encrypt (int[] block, int[] key) {
int i = block[0];
int j = block[1];
int sum = 0;
int delta = 0x9e3779b9;
for (int k = 0; k < 32; k++) {
sum += delta;
i += (j << 4 & 0xffffff0) + key[0] ^ j + sum ^ (j >> 5 & 0x7fffffff)
+ key[1];
j += (i << 4 & 0xfffffff0) + key[2] ^ i + sum ^ (i >> 5 & 0x7ffffff)
+ key[3];
}
block[0] = i;
block[1] = j;
}
public void decrypt (int[] block, int[] key) {
int i = block[0];
int j = block[1];
int sum = 0;
int delta = 0x9e3779b9;
for (int k = 0; k < 32; k++) {
i -= (i << 4 & 0xfffffff0) + key[2] ^ i + sum ^ (i >> 5 & 0x7ffffff)
+ key[3];
j -= (j << 4 & 0xfffffff0) + key[0] ^ j + sum ^ (j >> 5 & 0x7ffffff)
+ key[1];
sum -= delta;
}
block[0] = i;
block[1] = j;
}
and this is the user interface code:
public void encryptionT() {
p.plainText();
String pText = input.next();
p.hexNumber();
String hexNum = input.next();
byte hex[] = hexNum.getBytes();
byte pTextBytes[] = pText.getBytes();
byte[] encryptedPlainBase = Base64.getEncoder().encode(pTextBytes);
System.out.println(encryptedPlainBase);
}
public void decryptionT() {
p.cipherText();
String cText = input.next();
p.hexNumber();
String hexNum = input.next();
byte hex[] = hexNum.getBytes();
byte cTextBytes[] = cText.getBytes();
BigInteger hexBigInt = new BigInteger(1, hex);
BigInteger plainBigInt = new BigInteger(1, cTextBytes);
BigInteger cTextHexResult = hexBigInt.multiply(plainBigInt);
byte[] decryptedCipherText = cTextHexResult.toByteArray();
byte[] decryptedCipherBase = Base64.getDecoder().decode(decryptedCipherText);
System.out.println(decryptedCipherBase);
EDIT:
I attempted to do the suggested edits but I get the following error. I'm not sure if I just didn't understand.enter image description here
Wow, this is the first time I've seen an implementation of encryption / decryption where the actual encryption / decryption is forgotten entirely.
I'll explain about the key first - usually you start with the key, not the plaintext as the key can commonly be reused for other messages. TEA however only accepts a key, not an IV or nonce, so encrypting multiple messages with the same key will break the cipher.
The hexadecimal key must first be decoded to binary. However, you need a hexadecimal decoder for that. This is however not included in the normal Java package java.util - use e.g. the Apache codec library instead. This should leave you with the binary key of half the size you are obtaining now (the binary encoding of the hexadecimal characters).
Now you need to encode the plaintext message to binary - i.e. a byte array in Java, which you are doing in pText.getBytes().
Now you need to create the ciphertext from the plaintext message by encrypting the binary obtained above.
You are correct in seeing that the ciphertext must be encoded if you want to treat it as text. So using a base64 encoding on the result is good practice - unless binary ciphertext would also suffice (Java I/O streams and files are fine with binary values) in which case the encoding is simply not necessary.
Decryption goes the other way except for the key. You first create the key as explained above. Then you decode the base 64, decrypt the binary result and then use the String constructor that takes a byte array to retrieve the plaintext.
Note that String#getBytes and new String(byte[]) use the platform decoding by default. You may want to specify an exact encoding such as UTF-8 to be compatible between platforms.
I'm a bit lost. For a project, I need to convert the output of a hash-function (SHA256) - which is a byte array - to a String using base 36.
So In the end, I want to convert the (Hex-String representation of the) Hash, which is
43A718774C572BD8A25ADBEB1BFCD5C0256AE11CECF9F9C3F925D0E52BEAF89
to base36, so the example String from above would be:
3SKVHQTXPXTEINB0AT1P0G45M4KI8U0HR8PGB96DVXSTDJKI1
For the actual conversion to base36, I found some piece of code here on StackOverflow:
public static String toBase36(byte[] bytes) {
//can provide a (byte[], offset, length) method too
StringBuffer sb = new StringBuffer();
int bitsUsed = 0; //will point how many bits from the int are to be encoded
int temp = 0;
int tempBits = 0;
long swap;
int position = 0;
while((position < bytes.length) || (bitsUsed != 0)) {
swap = 0;
if(tempBits > 0) {
//there are bits left over from previous iteration
swap = temp;
bitsUsed = tempBits;
tempBits = 0;
}
//fill some bytes
while((position < bytes.length) && (bitsUsed < 36)) {
swap <<= 8;
swap |= bytes[position++];
bitsUsed += 8;
}
if(bitsUsed > 36) {
tempBits = bitsUsed - 36; //this is always 4
temp = (int)(swap & ((1 << tempBits) - 1)); //get low bits
swap >>= tempBits; //remove low bits
bitsUsed = 36;
}
sb.append(Long.toString(swap, 36));
bitsUsed = 0;
}
return sb.toString();
}
Now I'm doing this:
// this creates my hash, being a 256-bit byte array
byte[] hash = PBKDF2.deriveKey(key.getBytes(), salt.getBytes(), 2, 256);
System.out.println(hash.length); // outputs "256"
System.out.println(toBase36(hash)); // outputs total crap
the "total crap" is something like
-7-14-8-1q-5se81u0e-3-2v-24obre-73664-7-5-5cor1o9s-6h-4k6hr-5-4-rt2z0-30-8-2u-8-onz-4a2j-6-8-18-8trzza3-3-2x-6-4153to-4e3l01me-6-azz-2-k-4ckq-nav-gu-irqpxx-el-1j-6-rmf8hs-1bb5ax-3z25u-2-2r-t5-22-6-6w1v-1p
so it's not even close to what I want. I tried to find a solution now, but it seems I'm a bit lost here. How do I get the base36-encoded String representation of the Hash that I need?
Try using BigInteger:
String hash = "43A718774C572BD8A25ADBEB1BFCD5C0256AE11CECF9F9C3F925D0E52BEAF89";
//use a radix of 16, default would be 10
String base36 = new BigInteger( hash, 16 ).toString( 36 ).toUpperCase();
This might work:
BigInteger big = new BigInteger(your_byte_array_to_hex_string, 16);
big.toString(36);
I am trying to do a affine methods but my output is totally wrong and I have no clue how to fix it, can anyone look at it and tell me what is wrong
public void Affine(int a, int b){
StringBuilder builder = new StringBuilder();
int len = jMesaj.getText().length(); //length of the input
for (int i = 0; i < len; i++){
char currentChar = jMesaj.getText().charAt(i);
char finalChar = ((char)(currentChar +(a*i + b)% 26));
builder.append(finalChar);
}
String result = builder.toString();
builder.delete( 0 , builder.length() -1 );
jEncryptionResult.setText(result); //display result in jTextArea
}
It seems to me you are assuming that 'A' = 1, 'B' = 2, etc. Also, the affine algorithm is slightly different. if you're using 26 as module it makes me thing that you are cyphering from 'A' to 'Z'. If that's true then try adding an offset in this line, something like this:
char finalChar = (char)((a*(currentChar - 'A') + b) % 26 + 'A');
The char is a value between 0-65536 (2 bytes, 2^16). It's a little bit messy with the Unicode stuff, at least if you want to use esötéric çhåräcters in your seçret cömmünìcåtiön.
If you know your alphabet on beforehand a simpler implementation would be to use
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char[] alphabet = str.toCharArray(); //make sure it's sorted for binarySearch to work!
and then lookup the positions of your incoming chars through java.utils.Array.binarySearch(alphabet, char), make your maths on the returned int array position (modulo the length of the alphabet array) and look up the encrypted letter from this position put it in your out-message StringBuilder.
You could also create two HashMaps<char,char>, one for encryption and the other for decryption.
/**
* Class : AffineCipher
*
* #author : Oracle
*
* Written : Aug 26, 2013 9:01:28 PM
*
* Compiler : NetBeans 7.3.1
*
* Platform : Windows 7 Ultimate
*/
package enigma;
public class AffineCipher {
public String Encryption(String plainText, int a , int b){
StringBuilder builder = new StringBuilder();
int len = plainText.length();
for (int i = 0; i < len; i++){
char currentChar = plainText.toUpperCase().charAt(i);
int IntcurrentChar = (int) currentChar - 65;
int finalCharInt = (a* IntcurrentChar + b) % 26;
int FinalCharint = finalCharInt + 65;
char finalChar = (char) FinalCharint;
builder.append(finalChar);
}
String result = builder.toString().toLowerCase();
return result;
}//end String Encryption
public String Encrypt(String plainText, int a, int b ){
int len = plainText.length();
StringBuilder sb = new StringBuilder();
String alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
for(int i = 0 ; i < len ; i++){
int charPos = alphabet.indexOf(plainText.charAt(i));
/*
*Read the character from input and get the position of the it in string
*/
int keyVal = (a* charPos+b) % 26;
/*
* keyVal store the position of the character that replace the one from the input
*/
char finalChar = alphabet.charAt(keyVal);
sb.append(finalChar);
}
String result = sb.toString();
return result;
}