How to obtain the same lenght string encoding with Blowfish+Hex - blowfish

We're trying to encode several input strings with the same length (32) applying Blowfish + Hex encoding.
The problem is that not always the final coded strings have the same length as we expect (32 length strings).
Below you find the code used. Please, can you help to suggest what's wrong?
public static String encrypt(String clear, String key)
{
try
{
Security.setProperty("crypto.policy", "unlimited");
byte [] keyBytes = key.getBytes("ASCII");//toByteArray(key);
filelogger.info("Key coded in bytes "+keyBytes);
SecretKeySpec skey = new SecretKeySpec(keyBytes, "Blowfish");
byte [] clearBytes = clear.getBytes();//toByteArray(clear);
filelogger.info("Input string coded in bytes "+clearBytes);
Cipher ci = Cipher.getInstance("Blowfish");
ci.init(Cipher.ENCRYPT_MODE, skey);
// encrypt the clear bytes value
byte[] encoded = ci.doFinal(clearBytes);
filelogger.info("Blowfish output "+encoded);
return Base64.getEncoder().encodeToString(encoded);
}
catch (Exception e)
{
filelogger.error("Error while encrypting: " + e.toString());
logger.error("Error while encrypting: " + e.toString());
return Base64.getEncoder().encodeToString(new byte[0]);
}
}
Best regards

We have solved using the following solution:
Passing the option "Blowfish/ECB/NoPadding" to the getInstance function.
public byte[] encryptBlowfishECBNopadding(byte[] key, byte[] dati) {
byte[] output = null;
try {
SecretKeySpec KS = new SecretKeySpec(key, "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, KS);
output = cipher.doFinal(dati);
return output;
} catch (Exception ee) {
logger.error(ee.getMessage());
filelogger.error(ee.toString());
return new byte[0];
}
}
Encoding the result of the method as below:
byte[] encryptresult=encryptBlowfishECBNopadding(toByteArray(decriptedki),toByteArray(criptokeyhlr.getKeydata()));
String stringencriptedki=Hex.encodeHexString(encryptresult).toUpperCase();
In this manner every output string has the same length.
Thanks to all for the support!

Related

Xamrin UWP Release causes weird NullReferenceException (System.Security.Cryptography.PasswordDeriveBytes)

public static class CryptoHelper {
// This size of the IV (in bytes) must = (keysize / 8). Default keysize is 256, so the IV must be
// 32 bytes long. Using a 16 character string here gives us 32 bytes when converted to a byte array.
private const string initVector = "pemgail9uzpgzl88";
// This constant is used to determine the keysize of the encryption algorithm
private static int keysize = 256;
private static int getKeySize()
{
return 256;
}
//Encrypt
//public static byte[] EncryptString( string plainText, string passPhrase ) {
public static byte[] EncryptString(string toEncrypt, string salt)
{
byte[] initVectorBytes = Encoding.UTF8.GetBytes(initVector);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(toEncrypt);
byte[] keyBytes = new byte[126];
try
{
PasswordDeriveBytes password = new PasswordDeriveBytes(Encoding.UTF8.GetBytes(salt), null);
Debug.WriteLine(CryptoHelper.getKeySize());
Debug.WriteLine(password.ToString());
keyBytes = password.GetBytes(256 / 8);
} catch (Exception e)
{
Debug.WriteLine(e.StackTrace);
}
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
memoryStream.Close();
cryptoStream.Close();
return cipherTextBytes;
}
........
The call to "password.GetBytes(256 / 8);" results in a non catchable NullReferenceException
This happens only when the UWP App is in Release mode; UWP Debug as well as Andorid and IOS are fine.
Also I get a weird Debug Message:
"this._hash" war "null".
or
"this._hash" was "null". (translated)
Here you can see it in action
VS2019 Screenshot
To repuduce this issue the inputs for the function are:
toEncrypt "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwiZXhwIjoxNjE3MDAyMTEyfQ.C0CaGgfibM4z55MoANI2CiohUyew09r3_D_TpcQ6n1c8LmQd8BusSyF1SMEIQ3cO5uxE9Tnau0ZAT6D3kN3NcQ"
salt
"9x83m74tzrx9387x4mz98374zt90x8m273z948734z59"
Cause I cant see the detailed cause of this problem there it is basilcy not possible to get a workaround for this.
I was trying to make the same code work. The solution I found was to replace:
PasswordDeriveBytes password = new PasswordDeriveBytes(Encoding.UTF8.GetBytes(salt), null);
with:
Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passPhrase, Encoding.UTF8.GetBytes("12345678"));
and also add this:
symmetricKey.Padding = PaddingMode.Zeros;

LINQ/MVC webservice return json file or an empty array

i don't know really how to formulate this but what i want is to achieve is the following, read a JSON file from a storage (direct url) but if that JSON file does not exist it should return an empty array.
this is what i got so far (and works)
public object GetFromFile(int Code)
{
string uriPath = "http://mystorage.com/folder/" + Code + ".json";
var allText = (new WebClient()).DownloadString(uriPath);
object jsonObject = JsonConvert.DeserializeObject(allText);
return jsonObject;
}
it returns to me the requested list of codes as a array, now if the code does not exists on the storage, possible, then the webservice should just return and empty array []
desired result:
from file (works):
[{001},{002},{003}]
if file does not exist
[]
//The call to WebClient.DownloadString(string) will throw an exception if the
//uri does not exist, in your case, the json file does not exist
var allText = null;
object jsonObject = null;
try
{
allText = (new WebClient()).DownloadString(uriPath);
jsonObject = JsonConvert.DeserializeObject(allText);
}
catch(WebException ex)
{
jsonObject = new object[0];
}
It seems that you expect that the JSON-file contains a sequence of similar items, from the look of it a sequence of integer numbers.
If you already know that the JSON-file contains this type of objects, it is better to use the overload of DeserializeObject<int>.
IEnumerable<int> ReadNumbersFromWebClient(int Code)
{
string uriPath = "http://mystorage.com/folder/" + Code + ".json";
var downloadedText = DownloadText(uriPath);
return JsonConvert.DeserializeObject<int[]>(allText);
}
string DownloadText(string uriPath)
{
using (var webClient = new WebClient())
{
return webClient.DownloadString(uriPath);
}
}
You said that you wanted to return an empty sequence if the "file does not exist". I assume that you meant: "if the web client says there is no string to download"
I looked at WebClient.DownloadString, and I couldn't find what happens if you use an uriPath that does not exist. Do you get empty string, or an exception?
ICollection<int> ReadNumbersFromWebClient(int Code)
{
// in case of exception: return empty string
try
{
string uriPath = "http://mystorage.com/folder/" + Code + ".json";
var downloadedText = DownloadText(uriPath);
return JsonConvert.DeserializeObject<int[]>(allText);
}
catch (Exception exc) // or use specific exception
{
return new int[];
}
}
It would be neater if you let DownloadText catch the expression. In case of exception return empty string. Experiment what happens if you try to Deserialize an empty string. It will probably be an empty int[]

Load Json Data using Pig

I am trying to extract data from below mention json format by pig using jsonLoader():
{"Partition":"10","Key":"618897","Properties2":[{"K":"A","T":"String","V":"M "}, {"K":"B","T":"String","V":"N"}, {"K":"D","T":"String","V":"O"}]}
{"Partition":"11","Key":"618900","Properties2":[{"K":"A","T":"String","V":"W”"},{"K":"B","T":"String","V":"X"}, {"K":"C","T":"String","V":"Y"},{"K":"D","T":"String","V":"Z"}]}
Right now I am able to extract data from “partition” ,“key” and “V” for every array objects with the following code:
A= LOAD '/home/hduser/abc.jon' Using JsonLoader('Partition:chararray,Key:chararray,Properties2:{(K:chararray,T:chararray,V:chararray)},Timestamp:chararray');
B= foreach A generate $0,$1,BagToString(Properties2.V,'\t') as vl:chararray;
store B into './Result/outPut2';
From above code I am getting "Properties2" array value on the sequence basis not column basis, it is creating problem whenever sequence changed or new object comes in existence.
Please help me to extract data on the basis of column( K values.)
My Output
Expected Output
Thanks In Advance
You have two options here
1.Use elephant-bird which will give you a map of key and value.
A = LOAD '/apps/pig/json_sample' USING com.twitter.elephantbird.pig.load.JsonLoader('-nestedLoad') as (json:map[]);
B = FOREACH A GENERATE json#'Partition',json#'Key',json#'Properties2';
dump B;
will give you an output of :
(10,618897,{([T#String,K#A,V#M ]),([T#String,K#B,V#N]),([T#String,K#D,V#O])})
(11,618900,{([T#String,K#A,V#W”]),([T#String,K#B,V#X]),([T#String,K#C,V#Y]),([T#String,K#D,V#Z])})
Or you have to write a custom loader which has to do this
a).It should know what is the correct order of values that will be coming
for the key K
b).Go through each of these values and see if the json is missing any of this key and return an empty/null char for that location.
Am posting the getNext() method of the CustomJsonLoader which will do the same:
#Override
public Tuple getNext() throws IOException {
// TODO Auto-generated method stub
try {
boolean notDone = in.nextKeyValue();
if (!notDone) {
return null;
}
Text value = (Text) in.getCurrentValue();
List<String> valueList = new ArrayList<String>();
if (value != null) {
String jsonString = value.toString();
System.out.println(jsonString);
JSONParser parser = new JSONParser();
JSONObject obj = null;
try {
obj = (JSONObject) parser.parse(jsonString);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("obj is "+obj);
if (obj != null) {
String partition = (String) obj.get("Partition");
String key = (String) obj.get("Key");
valueList.add(partition);
valueList.add(key);
JSONArray innArr = (JSONArray) obj.get("Properties2");
char[] innKeys = new char[] { 'A', 'B', 'C', 'D' };
Map<String,String> keyMap = new HashMap<String,String>();
for (Object innObj : innArr) {
JSONObject jsonObj = (JSONObject) innObj;
keyMap.put(jsonObj.get("K")+"",jsonObj.get("V")+"");
}
for (int i = 0; i < innKeys.length; i++) {
char ch = innKeys[i];
if (keyMap.containsKey(ch+"")) {
valueList.add(keyMap.get(ch+""));
}else{
valueList.add("");
}
}
Tuple t = tupleFactory.newTuple(valueList);
return t;
}
}
return null;
} catch (InterruptedException e) {
}
}
and register it and run :
REGISTER udf/CustomJsonLoader.jar
A = LOAD '/apps/pig/json_sample' USING CustomJsonLoader();
DUMP A;
(10,618897,M,N,,O)
(11,618900,W,X,Y,Z)
Hope this helps!

play framework session returns wrong value with sha256

I am having a problem with the session in play framework 1.2.4. When I add a SHA256-hash of a particular String ("testDude5") to the session and retrieve it afterwards, the values are not the same. It doesn't happen with other Strings like "testDude1". Here is the sample code to reproduce the result.
package controllers;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import play.mvc.Controller;
public class ExampleController extends Controller
{
public static final String test1 = "testDude1";
public static final String test2 = "testDude5";
public static void set()
{
session.put("test1", getHash(test1));
session.put("test2", getHash(test2));
}
public static void get()
{
String output = "";
output += "Test 1 compare: ";
output += session.get("test1").equals(getHash(test1)) ? "success" : "failed";
output += "\n";
output += "Test 2 compare: ";
output += session.get("test2").equals(getHash(test2)) ? "success" : "failed";
output += "\n";
renderText(output);
}
/**
* Generates the hash value for a password.
*
* #param password
* #return hash
*/
public static String getHash(String password)
{
// Create an digest object
MessageDigest md;
try
{
// Try to get sha-265
md = MessageDigest.getInstance("SHA-256");
// Encrypt the password
md.update(password.getBytes("UTF-8"));
// Get the encrypted password
byte[] digest = md.digest();
// Convert byte array to String
String str = new String(digest);
// Return encrypted password
return str;
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
return null;
}
}
I am totally puzzled by this. Does anyone have an idea whats going on there. Thanks for any advice.
Cheers
The problem is in your getHash function. There is nothing wrong with play framework session.
public static String getHash(String password) {
....
// Get the encrypted password
byte[] digest = md.digest();
// Convert byte array to String
String str = new String(digest); // DON'T do this with digest!
// The behavior is unspecified.
According to Java API doc, this constructor "Constructs a new String by decoding the specified array of bytes using the platform's default charset...The behavior of this constructor when the given bytes are not valid in the default charset is unspecified". However your hash digest may contains something not valid in the default charset.
Play framework provides a nice utility function Codec.byteToHeString() to transform digest in byte[] into hex string. This might be just what you need.
// Codec resides in play.libs
String str = Codec.byteToHexString(digest);

How do I read and write UTF-8 encoding from java assets folder? I have the code, but its not working. I get �D�nde est� / D�nde

private void CopyAssets2() {
AssetManager assetManager = getAssets();
String[] files = null;
try {
files = assetManager.list("");
} catch (IOException e) {
Log.e("File Error", e.getMessage());
}
for (String filename : files) {
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(filename);
out = new FileOutputStream("/sdcard/Translate/" + filename);
copyFile2(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch (Exception e) {
Log.e("Save Error", e.getMessage());
}
}
}
private void copyFile2(InputStream in, OutputStream out)
throws IOException {
char[] buffer = new char[1024];
Reader reader = new BufferedReader( new InputStreamReader(in, "UTF-8"));
Writer writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
int read;
while ((read = reader.read(buffer)) != -1) {
writer.write(buffer, 0, read);
}
reader.close();
writer.flush();
writer.close();
}
Im getting the inputstream with assetManager, and passing it as a parameter of reader with UTF-8 encoding specified.
I'm also doing writing to the outputstream filepath with writer in UTF-8
The file is read and written, but the encoding is still wrong. I get characters like these:
Where are... = �D�nde est� / D�nde
What I am doing wrong?
Are you sure the input file is encoded in UTF-8? The � you see in the output is a character that is used as a replacement for byte sequences that could not be converted into characters when reading.
You could make a binary copy instead of decoding and encoding text:
byte[] buffer = new byte[1024];
InputStream reader = new BufferedInputStream(in);
OutputStream writer = new BufferedOutputStream(out);
int read;
while ((read = reader.read(buffer)) != -1) {
writer.write(buffer, 0, read);
}

Resources