Encrypting a string in Cyrillic using XOR - java

I want to encrypt the string with XOR. The source text is in Cyrillic. After encrypting, I get the hieroglyphs, how can I fix it? I'll use the UTF-8 encoding.
String text = "Какой-нибудь русский текст"; // some cyrillic text
String sKey = LFSR(); // return string "10011010" for example
System.out.println("[PSP]: key: " + sKey); // output: 10011010
byte[] txt = text.getBytes(StandardCharsets.UTF_8);
byte[] key = sKey.getBytes(StandardCharsets.UTF_8);
byte[] res = new byte[txt.length];
for (int i = 0; i < txt.length; ++i) {
res[i] = (byte) (txt[i] ^ key[i % key.length]);
}
try {
System.out.println(new String(res, StandardCharsets.UTF_8));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Output:
ފ���������������������������������������
I think it's because the byte values are negative.

Related

Hashing Results From C# and Java are Different

I'm trying to hash data "text" to be transferred from Java Service to C# Service.
I'm using SHA256 as a Hashing algorithm, but despite the values and the salt being the same the result doesn't.
Here is my C# snippet
public string Sign(string textToHash, string salt){
byte[] convertedHash = new byte[salt.Length / 2];
for (int i = 0; i < salt.Length / 2; i++)
convertedHash[i] = (byte)int.Parse(salt.Substring(i * 2, 2), NumberStyles.HexNumber);
HMAC hasher = new HMACSHA256(convertedHash);
string hexHash = "";
using (hasher)
{
byte[] hashValue = hasher.ComputeHash(Encoding.UTF8.GetBytes(textToHash));
foreach (byte b in hashValue)
{
hexHash += b.ToString("X2");
}
}
return hexHash;
}
And, here is the Java snippet
public static String sign(String textToHash, String salt){
byte[] convertedHash = new byte[salt.length() / 2];
for (int i = 0; i < salt.length() / 2; i++)
{
convertedHash[i] = (byte)Integer.parseInt(salt.substring(i * 2, i * 2 + 2),16);
}
String hashedText = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(convertedHash);
byte[] bytes = md.digest(textToHash.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte aByte : bytes) {
sb.append(Integer.toString((aByte & 0xff) + 0x100, 16).substring(1));
}
hashedText = sb.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return hashedText;
}
In Java, I also tried
convertedHash = salt.getBytes();
But I got different results also.
Tests:
salt = ABCDEFG
text = hashme
Result in C#
70B38047C28FFEDCF7275C428E65310671CADB65F11A5C9A8CFBB3CF52112BA3
Result in Java
a8bc36606aade01591a1d12c8b3c87aca1fe55def79740def03a90b49f2c6b7c
So, any help about why the results aren't the same.
Thanks in advance.
To mimic the Java hashing, I used SHA256Managed rather than HMACSHA256 in C#
public static string Sign(string data, string salt)
{
UTF8Encoding encoder = new UTF8Encoding();
SHA256Managed sha256hasher = new SHA256Managed();
byte[] convertedHash = new byte[salt.Length / 2];
for (int i = 0; i < salt.Length / 2; i++)
convertedHash[i] = (byte)int.Parse(salt.Substring(i * 2, 2), NumberStyles.HexNumber);
byte[] dataBytes = encoder.GetBytes(data);
byte[] bytes = new byte[convertedHash.Length + dataBytes.Length];
Array.Copy(convertedHash, bytes, convertedHash.Length);
Array.Copy(dataBytes, 0, bytes, convertedHash.Length, dataBytes.Length);
byte[] hashedBytes = sha256hasher.ComputeHash(bytes);
return hashedBytes.Aggregate("", (current, t) => current + t.ToString("X2"));
}
HMACSHA256 is not a pure SHA-256.

Md5 to String in android studio

I am using Md5 for sharedpref
now when I get the data shared but see encrypted it
public static String md5(final String s) {
final String MD5 = "MD5";
try {
// Create MD5 Hash
MessageDigest digest = java.security.MessageDigest
.getInstance(MD5);
digest.update(s.getBytes());
byte messageDigest[] = digest.digest();
// Create Hex String
StringBuilder hexString = new StringBuilder();
for (byte aMessageDigest : messageDigest) {
String h = Integer.toHexString(0xFF & aMessageDigest);
while (h.length() < 2)
h = "0" + h;
hexString.append(h);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
this codes for get the data from shared, I can not see data, i only see the encripted md5
sharedPreferences=getSharedPreferences(nameshe,MODE_PRIVATE);
String nam=sharedPreferences.getString(sa,"jan");
String names =md5(nam);
textView.setText(names);

Bouncycastle library join bytes and string

Hi I'm using Bouncycastle library to create md5 hash from image byte array and client id string. But from Recognize.im API I'm still getting error invalid hash, is there anything wrong?
String myMd5(String myString, byte[] byteArray){
MD5Digest md5 = new MD5Digest();
md5.reset();
try {
md5.update(myString.getBytes("UTF-8"), 0 , myString.length());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
md5.update(byteArray, 0, byteArray.length);
byte[] digest = new byte[md5.getDigestSize()];
md5.doFinal(digest, 0);
StringBuffer sb = new StringBuffer();
for (int i = 0; i < digest.length; ++i) {
sb.append(Integer.toHexString((digest[i] & 0xFF) | 0x100)
.substring(1, 3));
}
return sb.toString();
}

Bouncycastle java encoding/decoding. Missing bytes?

I need to encode/decode a text using CBC Rijndael encryption.
Input:
The force is strong in this looooooooooooooooooo000000000oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong String
Encoded input: ?†´Ú½mΗ“AŽyÝ¢ƒô]5X-å;’Bdž.̵¼èüÈíÖXÈ*©Ã¼ç–hKBµ$híƒEu-ȸU ¤‘AÓÈÿ?Ÿûä¸:OW?B>ÐZ²ñ
,­zÅë(C’®5ÐixRópE%€.#vhrm6µ5©bŠ?Ç¡$q¿J^÷g“e†ì??bt ì%q‘ÕQÚ5µã?ƒ
Decoded input:
"The force is strong in this looooooooooooooooooo000000000ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo " - and 32 spaces in place of the ending (byte value is 0)
I'm missing the final bytes. Can anyone tell me why ?
This is my code:
public class BouncyDecoder {
byte[] IV = null;
byte[] encryptionKey = null;
Cipher cipher;
SecretKeySpec key;
BlockCipher blockCipher;
ParametersWithIV _param;
PaddedBufferedBlockCipher mode;
int blockSize;
public BouncyDecoder() {
Security.addProvider(new BouncyCastleProvider());
try {
IV = "1234567891234567891234567891234".getBytes("UTF-8");
encryptionKey = "1234567891123453456789123456781".getBytes("UTF-8");
blockCipher = new CBCBlockCipher(new RijndaelEngine(256));
_param = new ParametersWithIV(new KeyParameter(encryptionKey), IV);
mode = new PaddedBufferedBlockCipher(blockCipher);
blockSize = blockCipher.getBlockSize();
} catch (Exception e) {
}
}
public byte[] decrypt(byte[] encodedText) {
byte[] decoded = new byte[mode.getOutputSize(encodedText.length)];
try {
mode.init(false, _param);
int bytesProcessed = 0;
int i=0;
for (i = 0; i < (encodedText.length / 32) ; i++){
bytesProcessed += mode.processBytes(encodedText, i * blockSize, blockSize, decoded, bytesProcessed);
}
mode.doFinal(decoded, (i-1)*blockSize);
} catch (Exception e) {
}
return decoded;
}
public byte[] encrypt(byte[] normalText) {
byte[] encryptedText = new byte[mode.getOutputSize(normalText.length)];
try {
mode.init(true, _param);
int bytesProcessed = 0;
int i=0;
for (i = 0; i < (normalText.length / 32); i++) {
bytesProcessed += mode
.processBytes(normalText, i * blockSize, blockSize, encryptedText, bytesProcessed);
}
mode.doFinal(encryptedText, (i-1)*blockSize);
} catch (Exception e) {
e.printStackTrace();
}
return encryptedText;
}
}
Your loop doesn't seem process all of the bytes in input string:
for (i = 0; i < (normalText.length / 32); i++) {
bytesProcessed += mode
.processBytes(normalText, i * blockSize, blockSize, encryptedText, bytesProcessed);
}
it only processes bytes from 0 to (text.Length/32)*blockSize.
So if length of input array is 35 bytes, last 3 bytes are never getting processed.
What about using something like this instead:
bytesProcessed = mode.processBytes(normalText, 0, normalText.length, encryptedText,0);
//second argument of doFinal is offset in output buffer.
mode.doFinal(encryptedText, bytesProcessed);
If this one is going to work you'll definitely know that the problem is off-by-one error in loop counter.
UPDATE: Or you can try something like this if you want to encrypt a block at a time:
for(int i=0; i<=(normalText.length/blockSize); i++) {
int offset = i*blockSize;
//To handle last block of bytes in input
int len = Math.min(blockSize,normalText.length-offset);
bytesProcessed += mode.processBytes(normalText,offset,len,encryptedText,bytesProcessed);
}
mode.doFinal(encryptedText, bytesProcessed);
Same goes for decryption

Get MD5 String from Message Digest

I understand how it works but if I want to print out the MD5 as String how would I do that?
public static void getMD5(String fileName) throws Exception{
InputStream input = new FileInputStream(fileName);
byte[] buffer = new byte[1024];
MessageDigest hash = MessageDigest.getInstance("MD5");
int read;
do {
read = input.read(buffer);
if (read > 0) {
hash.update(buffer, 0, read);
}
} while (read != -1);
input.close();
}
You can get it writing less:
String hex = (new HexBinaryAdapter()).marshal(md5.digest(YOUR_STRING.getBytes()))
String input = "168";
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] md5sum = md.digest(input.getBytes());
String output = String.format("%032X", new BigInteger(1, md5sum));
or
DatatypeConverter.printHexBinary( MessageDigest.getInstance("MD5").digest("a".getBytes("UTF-8")))
Try this
StringBuffer hexString = new StringBuffer();
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hash = md.digest();
for (int i = 0; i < hash.length; i++) {
if ((0xff & hash[i]) < 0x10) {
hexString.append("0"
+ Integer.toHexString((0xFF & hash[i])));
} else {
hexString.append(Integer.toHexString(0xFF & hash[i]));
}
}
You can also use Apache Commons Codec library.
This library includes methods public static String md5Hex(InputStream data) and public static String md5Hex(byte[] data) in the DigestUtils class.
No need to invent this yourself ;)
First you need to get the byte[] output of the MessageDigest:
byte[] bytes = hash.digest();
You can't easily print this though (with e.g. new String(bytes)) because it's going to contain binary that won't have good output representations. You can convert it to hex for display like this however:
StringBuilder sb = new StringBuilder(2 * bytes.length);
for (byte b : bytes) {
sb.append("0123456789ABCDEF".charAt((b & 0xF0) >> 4));
sb.append("0123456789ABCDEF".charAt((b & 0x0F)));
}
String hex = sb.toString();
Shortest way:
String toMD5(String input) {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] raw = md.digest(input.getBytes());
return DatatypeConverter.printHexBinary(raw);
}
Just remember to handle the exception.
With the byte array, result from message digest:
...
byte hashgerado[] = md.digest(entrada);
...
for(byte b : hashgerado)
System.out.printf("%02x", Byte.toUnsignedInt(b));
Result (for example):
89e8a9f68ad3c4bba9b9d3581cf5201d
/**
* hashes:
* e7cfa2be5969e235138356a54bad7fc4
* 3c9ec110aa171b57bb41fc761130822c
*
* compiled with java 8 - 12 Dec 2015
*/
public static String generateHash() {
long r = new java.util.Random().nextLong();
String input = String.valueOf(r);
String md5 = null;
try {
java.security.MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
//Update input string in message digest
digest.update(input.getBytes(), 0, input.length());
//Converts message digest value in base 16 (hex)
md5 = new java.math.BigInteger(1, digest.digest()).toString(16);
}
catch (java.security.NoSuchAlgorithmException e) {
e.printStackTrace();
}
return md5;
}
FYI...
In certain situations this did not work for me
md5 = new java.math.BigInteger(1, digest.digest()).toString(16);
but this did
StringBuilder sb = new StringBuilder();
for (int i = 0; i < digest.length; i++) {
if ((0xff & digest[i]) < 0x10) {
sb.append("0").append(Integer.toHexString((0xFF & digest[i])));
} else {
sb.append(Integer.toHexString(0xFF & digest[i]));
}
}
String result = sb.toString();
Call hash.digest() to finish the process. It will return an array of bytes.
You can create a String from a byte[] using a String constructor, however if you want a hex string you'll have to loop through the byte array manually and work out the characters.
This is another version of #anything answer:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < digest.length; i++) {
if ((0xff & digest[i]) < 0x10) {
sb.append("0").append(Integer.toHexString((0xFF & digest[i])));
} else {
sb.append(Integer.toHexString(0xFF & digest[i]));
}
}
String result = sb.toString();

Categories

Resources