Как бы я маскировался в этом коде?
I discovered that in java does not support 32 but integers. I had errors that i was getting when I had it in that form. So I switched over to BigInteger think it would fix this problem. So I kept on using BigInteger through the left and right shifting. Now i'm facing the problem of not getting the right output.Я использую BigInteger для хранения 128-байтового ключа. Но когда я запускаю свой код, он дает мне неправильный вывод. И то, что я читал, было то, что можно использовать маскировку, которая решила бы эту проблему.
Что я уже пробовал:
when inputting the plaintText as: "0x0123456789ABCDEF" Output is: Original Plain Text:0x0123456789ABCDEF CipherText:0xa0761126d09724fd Decrypted CipherText is:0x8d5a4a234b3c6720 But when i input: 0x123456789ABCDEF The output is: Invalid block size! Original Plain Text:0x123456789ABCDEF CipherText:null What am I doing wrong? Here's my code: import java.math.BigInteger; public class TEA { BigInteger [] K ; //128 bits key private String plainText; public static final BigInteger delta = new BigInteger("9e3779b9",16); //constructor receives a string of plaintext and 128 bit key in hexadecimal public TEA(String plainText, String key) { parseKey(key); } //constructor receives a hexadecimal public TEA(String key) { parseKey(key); } //parses a 128 bit key, given in hexadecimal form, and store its value in 4 integers (total of 128 bits), private void parseKey(String key) { if(key.substring(0,2).equals("0x")) key= key.substring(2); //validating input if(key.length() != 32) { System.out.println("Invalid key size!"); return; } //dividing the key into 4 strings String[] kStr = new String[4]; int index=-1; for(int i=0; i<key.length(); i++) { if(i%8 == 0) { index++; kStr[index]=""; } kStr[index] = kStr[index] + key.charAt(i); } //converting the 4 hex strings into 4 integers K= new BigInteger[4]; for(int i=0; i<4; i++) K[i] = new BigInteger(kStr[i], 16); } //receives a plaintext block of 64 bits in hexadecimal to be encrypted //returns the cipher block String encryptBlock(String plainTextBlock) { if(plainTextBlock.substring(0,2).equals("0x")) plainTextBlock= plainTextBlock.substring(2); //validating input if(plainTextBlock.length()!=16) { System.out.println("Invalid block size!"); return null; } //separating the string block into left and right blocks String LStr = plainTextBlock.substring(0, 8); //left block (32 bit) String RStr = plainTextBlock.substring(8); //right block (32 bit) //converting left and right blocks to integers BigInteger L = new BigInteger(LStr, 16); BigInteger R = new BigInteger(RStr, 16); BigInteger sum= new BigInteger("0"); //32 rounds for(int i=0; i<32; i++) { sum = sum.add(delta); L= sum(L, (sum(shiftLeft(R,4),K[0])) .xor(sum(R,sum)) .xor(sum(shiftRight(R,5),K[1]))) ; R= sum(R, (sum(shiftLeft(L,4),K[2])) .xor(sum(L,sum)) .xor(sum(shiftRight(L,5),K[3]))) ; //R= R.add( (shiftLeft(R,4).add(K[2])).xor(L.add(sum)).xor(shiftRight(L,5).add(K[3])) ); } //joining back the blocks as hex String cipherBlock = "0x"+L.toString(16)+R.toString(16)+""; return cipherBlock; } //receives a ciphertext block of 64 bits in hexadecimal to be decrypted //returns the plaintext block String decryptBlock(String cipherBlock) { if(cipherBlock.substring(0,2).equals("0x")) cipherBlock= cipherBlock.substring(2); //validating input if(cipherBlock.length()!=16) { System.out.println("Invalid block size!"); return null; } //separating the string block into left and right blocks String LStr = cipherBlock.substring(0, 8); //left block (32 bit) String RStr = cipherBlock.substring(8); //right block (32 bit) //converting left and right blocks to integers BigInteger L = new BigInteger(LStr, 16); BigInteger R = new BigInteger(RStr, 16); BigInteger sum= shiftLeft(delta,5); //32 rounds for(int i=0; i<32; i++) { R= subtract(R, (sum(shiftLeft(L,4),K[2])) .xor(sum(L,sum)) .xor(sum(shiftRight(L,5),K[3]))) ; L= subtract(L, (sum(shiftLeft(R,4),K[0])) .xor(sum(R,sum)) .xor(sum(shiftRight(R,5),K[1]))) ; //R= R.subtract( (L.shiftLeft(4).add(K[2])).xor(L.add(sum)).xor(L.shiftRight(5).add(K[3])) ); //L= L.subtract( (R.shiftLeft(4).add(K[0])).xor(R.add(sum)).xor(R.shiftRight(5).add(K[1])) ); sum = sum.subtract(delta); } //joining back the blocks as hex String plainTextBlock = "0x"+L.toString(16)+R.toString(16)+""; return plainTextBlock; } private BigInteger shiftLeft(BigInteger x, int steps) { BigInteger shifted=null; boolean negative =false; String xStr = x.toString(2); //removing negative sign while shifting (currently) if(xStr.charAt(0)=='-') { negative= true; xStr = xStr.substring(1); } int additionalSize = 32- xStr.length(); for(int i=0; i<additionalSize; i++) xStr= "0"+xStr; for(int i=0; i<steps; i++) { xStr = xStr.substring(1); xStr = xStr+"0"; } //one last addition of negative sign if the number is negative if(negative==true) xStr= "-"+xStr; //System.out.println(xStr); shifted = new BigInteger(xStr,2); return shifted; } private BigInteger shiftRight(BigInteger x, int steps) { BigInteger shifted=null; boolean negative = false; String xStr = x.toString(2); //removing negative sign while shifting (currently) if(xStr.charAt(0)=='-') { negative= true; xStr = xStr.substring(1); } int additionalSize = 32- xStr.length(); for(int i=0; i<additionalSize; i++) xStr= "0"+xStr; for(int i=0; i<steps; i++) { xStr = xStr.substring(0,xStr.length()-1); xStr = "0"+xStr; } //one last addition of negative sign if the number is negative if(negative==true) xStr= "-"+xStr; shifted = new BigInteger(xStr,2); return shifted; } private BigInteger sum(BigInteger a, BigInteger b) { BigInteger sum = a.add(b); String sumStr = sum.toString(2); if(sumStr.length()>32) { int diff = sumStr.length()- 32; sumStr = sumStr.substring(diff); } BigInteger newSum = new BigInteger(sumStr,2); return newSum; } private BigInteger subtract(BigInteger a, BigInteger b) { BigInteger sub = a.subtract(b); String subStr = sub.toString(2); if(subStr.length()>32) { int diff = subStr.length()- 32; subStr = subStr.substring(diff); } BigInteger newSub = new BigInteger(subStr,2); return newSub; } public static void main(String[] args) { String plainText="0x0123456789ABCDEF"; String key= "0xA56BABCD00000000FFFFFFFFABCDEF01"; TEA tea = new TEA(key); String cipherText = tea.encryptBlock(plainText); System.out.println("Original Plain Text:"+plainText); System.out.println("CipherText:"+cipherText); System.out.println("Decrypted CipherText is:"+tea.decryptBlock(cipherText)); } }
Richard Deeming
Почему вы думаете, что Java не поддерживает 32-битные целые числа?
Примитивные типы данных (учебные пособия Java™ > изучение языка Java > основы языка)[^]
"int: по умолчанию тип данных int представляет собой 32-битное целое число дополнения со знаком два, которое имеет минимальное значение -231 и максимальное значение 231-1. в Java SE 8 и более поздних версиях тип данных int можно использовать для представления 32-разрядного целого числа без знака, которое имеет минимальное значение 0 и максимальное значение 232-1. Использовать integer класс использовать int тип данных целое число без знака."
Chad3F
Примечание: используйте key.startsWith("0x") вместо создания подстроки и сравнения ее с "0x".