Crazy exception at AES Decryption - BadPaddingException - exception

I'm having some trouble here while trying to decode some encrypted text.
CheckpswdBasedKey is always returning false, because of the BadPaddingException at c.doFInal
I'm using AES, basicaly the encryption:
public static String generatePswdBasedKey(String password){
String finalKey = null;
SecretKey sk = null;
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, IT, KEY_LENGTH);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
sk = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance(Cifrador.AES_MODE);//AES_MODE = AES/CBC/PKCS5Padding
IvParameterSpec ivParams = new IvParameterSpec(iv);//IV already initialized
cipher.init(Cipher.ENCRYPT_MODE, sk, ivParams);
byte pwdbytes[] = password.getBytes();//I also tried using Base64 to decode... without success
byte cc[] = cipher.doFinal(pwdbytes);
finalKey = Base64.encodeToString(cc, false); //.encodeToString(byte[] sArr, boolean lineSep)
return finalKey;
Now decrypt mode:
//This method compares a password received from keyboard with the decrypted password (decrypting output from generatePswdBasedKey(String password))
public static boolean checkPswdBasedKey(String password, String passwordInput){
byte bufferBytes[] = Base64.decode(password);
SecretKey sk = new SecretKeySpec(bufferBytes, 0, bufferBytes.length, "AES"); //Also tried new SecretKeySPec(bufferBytes, "AES");...
Cipher c = Cipher.getInstance(Cifrador.AES_MODE);//AES_MODE = AES/CBC/PKCS5Padding
IvParameterSpec ivParams = new IvParameterSpec(iv);//IV already initialized
c.init(Cipher.DECRYPT_MODE, sk, ivParams);
byte result[] = c.doFinal(bufferBytes);
String resultStr = Base64.encodeToString(result, false); //.encodeToString(byte[] sArr, boolean lineSep)
if(passwordInput.equalsIgnoreCase(resultStr)){
return true;
}
return false;
}
I compared bytes from iv #checkPswdBasedKey and iv #generatePswdBasedKey and they are all the same. Same happens to the secretkey #checkPswdBasedKey (i get those bytes with: sk.getEncoded() ) and secretkey #generatePswdBasedKey... they are all equal.
So basically when i decrypt i know i'm using the same key, same IV and same message... and an appropiate length (16 bytes key, 16 bytes msg, 16 bytes iv, using AES 128) Any idea?

As Joachim Isaksson commented, if you want to implement a password check, you ought to use a secure hash representation of the password, that is not reversible. This way, the password can't be obtained by decryption even if the hash + key is compromised.
Anyway, in your generatePswdBasedKey you use the PBKDF2WithHmacSHA1 algorithm to generate a SecretKey, and then use that key to encrypt the password. Now you have two options to verify the password in checkPswdBasedKey. Either you:
encrypt the password the same way as in generatePswdBasedKey and compare that they give the same encrypted string
or you
decrypt the encrypted version and compare the result with the password in clear.
I presume that you try the later approach as you init your cipher for decrypt with:
c.init(Cipher.DECRYPT_MODE, sk, ivParams);
Hovewer, for that approach to work you need to instantiate your SecretKey the same way
as you did in generatePswdBasedKey - currently you end up with two different keys.
In generatePswdBasedKey:
SecretKey sk = null;
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, IT, KEY_LENGTH);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
sk = new SecretKeySpec(keyBytes, "AES");
In checkPswdBasedKey:
byte bufferBytes[] = Base64.decode(password);
SecretKey sk = new SecretKeySpec(bufferBytes, 0, bufferBytes.length, "AES");
When that is fixed, you also need to look at your compare logic. You should not do a Base64 encoding of your result before the compare - and the compare ought to be case sensitive.
Don't use:
byte result[] = c.doFinal(bufferBytes);
String resultStr = Base64.encodeToString(result, false);
if (passwordInput.equalsIgnoreCase(resultStr)) {
return true;
}
But instead use:
byte result[] = c.doFinal(bufferBytes);
String resultStr = new String(result);
if (passwordInput.equals(resultStr)) {
return true;
}

Related

Encrypt nodejs data to mysql

I'm currently using Crypto to encrypt/ decrypt data, but, if the server restarts, the decrypt won't work anymore. That's what i'm currently using =>
const crypto = require("crypto");
const algorithm = "aes-256-cbc";
const initVector = crypto.randomBytes(16);
const Securitykey = crypto.randomBytes(32);
function encrypt(text){
const cipher = crypto.createCipheriv(algorithm, Securitykey, initVector);
let encryptedData = cipher.update(text, "utf-8", "hex");
encryptedData += cipher.final("hex");
return encryptedData;
}
function decrypt(text){
const decipher = crypto.createDecipheriv(algorithm, Securitykey, initVector);
let decryptedData = decipher.update(text, "hex", "utf-8");
decryptedData += decipher.final("utf8");
return decryptedData;
}
And this is the error I get if i want to decrypt something after server restart
Error: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
So as I can see from the code your IV and Key are randomly generated and I am assuming that you are not saving them anywhere.
const initVector = crypto.randomBytes(16);
const Securitykey = crypto.randomBytes(32);
So basically on server restart you are getting a new pair of IV and key, so when you are decrypting it is not matching with the Key and IV used at the time of encryption.
My suggested solution :
const crypto = require("crypto");
const algorithm = "aes-256-cbc";
const initVectorString = "Any random hex string of 16bytes"; // You can store this into a env file
const SecuritykeyString = "Random security hex string of 32bytes"; // You can store this into a env file
const initVector = Buffer.from(initVectorString, "hex");
const Securitykey = Buffer.from(SecurityKeyString, "hex");
function encrypt(text){
const cipher = crypto.createCipheriv(algorithm, Securitykey, initVector);
let encryptedData = cipher.update(text, "utf-8", "hex");
encryptedData += cipher.final("hex");
return encryptedData;
}
function decrypt(text){
const decipher = crypto.createDecipheriv(algorithm, Securitykey, initVector);
let decryptedData = decipher.update(text, "hex", "utf-8");
decryptedData += decipher.final("utf8");
return decryptedData;
}
Update:-
So if you are using a utf-8 string for IV then the string length should be 16 characters only (if you are using only 1 byte characters a-zA-Z0-9 all are 1 byte characters) and you need to change the encoding type in Buffer.from() function from "Hex" to "utf-8".
Similar for the security key length of the string should be 32 characters only and you need to change the encoding type in Buffer.from() function from "Hex" to "utf-8".

How to Add a shapefile data to postgis(postgres) using c#

am trying to add shapefile data to postgis using c#
string path = browse_path.Text;
ProcessStartInfo startInfo = new ProcessStartInfo("CMD.exe");
Process p = new Process();
startInfo.RedirectStandardInput = true;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
p = Process.Start(startInfo);
string chgdir = #"chdir " + #"C:\Program Files\PostgreSQL\9.4\bin\";
p.StandardInput.WriteLine(chgdir);
string pass = #"set PGPASSWORD=postgres";
p.StandardInput.WriteLine(pass);
string cmd = #"shp2pgsql -I -s 4326 " + path + " public.states | psql -U postgres -d postgres";
p.StandardInput.WriteLine(cmd);
p.WaitForExit();
p.Close();`
and for waiting almost 7-8 mins its not working. my shp file is 160 kb only.. but the command is working fine if i run it in the cmd rather then using code..
This is a function I wrote to import shapefiles to PG. It uses Nuget packages CliWrap and Npgsql and I just copied shp2pgsql and its dependencies to a project folder 'Tools' so it can be run on a machine that doesn't have PostgreSQL installed. Its a bit messy and you might need to add error handling but it worked for my needs.
public async static Task<bool> OutputSHPtoPSGLAsync(string shpfile, string host, string user, string pwd, string db, string schema = "public", bool dropIfExists = true, string table = "[SHPNAME]")
{
FileInfo shp = new FileInfo(shpfile);
if (!shp.Exists) return false;
if (table == "[SHPNAME]") table = Path.GetFileNameWithoutExtension(shpfile).ToLower();
string args = string.Format("{0} {1}.{2}", shpfile, schema, table);
Command cli = Cli.Wrap(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, #"tools\shp2pgsql.exe")).WithArguments(args);
ExecutionResult eo = await cli.ExecuteAsync();
string sql = eo.StandardOutput;
if (dropIfExists) sql = sql.Replace("CREATE TABLE", string.Format("DROP TABLE IF EXISTS \"{0}\".\"{1}\";\r\nCREATE TABLE", schema, table));
string constring = string.Format("Host={0};Username={1};Password={2};Database={3}", host, user, pwd, db);
using (NpgsqlConnection connection = new NpgsqlConnection(constring))
{
connection.Open();
new NpgsqlCommand(sql, connection).ExecuteNonQuery();
}
return true;
}
I was looking at NetTopologySuite which has type definitions compatible with Npgsql and PostGIS but its all still pre-release and couldn't be bothered working it out.

How to register Quartz Scheduler with Windsor?

What I have tried so far?
container.Register(Component.For<Quartz.IScheduler>()
.UsingFactoryMethod(() => GetQuartzScheduler())
.LifeStyle.PerWebRequest);
Inside GetQuartzScheduler()
string tcp = string.Format("tcp://DevMachine:8888/QuartzScheduler");
NameValueCollection properties = new NameValueCollection();
properties["quartz.scheduler.instanceName"] = string.Format("MyQuartz_{0}", alias);
// set thread pool info
properties["quartz.scheduler.proxy"] = "true";
properties["quartz.threadPool.threadCount"] = "0";
properties["quartz.scheduler.proxy.address"] = tcp; //tcp variable is set before
Quartz.ISchedulerFactory sf = new Quartz.Impl.StdSchedulerFactory(properties);
sched = sf.GetScheduler(); //<--**Throws exception**
The exception is:
Factory method creating instances of component 'Late bound Quartz.IScheduler' returned null. This is not allowed and most likely a bug in the factory method.
Any suggestions to correct this?

what is an encoding type when client sends message to websocket server?

somebody know what is encoding type of message that client sends to websocket server?
I'm studying this site
http://blogs.claritycon.com/blog/2012/01/18/websockets-with-rfc-6455/
and from what this site teaches me, below are decoding code to get message from client in server side!!!
public string HybiDecode(byte[] data)
{
byte firstByte = data[0];
byte secondByte = data[1];
int opcode = firstByte & 0x0F;
bool isMasked = ((firstByte & 128) == 128);
int payloadLength = secondByte & 0x7F;
if (!isMasked) { return null; } // not masked
if (opcode != 1) { return null; } // not text
List<int> mask = new List<int>();
for (int i = 2; i < 6; i++)
{
mask.Add(data[i]);
}
int payloadOffset = 6;
int dataLength = payloadLength + payloadOffset;
List<int> unmaskedPayload = new List<int>();
for (int i = payloadOffset; i < dataLength; i++)
{
int j = i - payloadOffset;
unmaskedPayload.Add(data[i] ^ mask[j % 4]);
}
return ToAscii(unmaskedPayload.Select(e => (byte)e).ToArray());
}
public string ToAscii(byte[] data)
{
System.Text.ASCIIEncoding decoder = new System.Text.ASCIIEncoding();
return decoder.GetString(data, 0, data.Length);
}
but now I'm studying in C language so I have to convert ToAscii() to C language!
but... from what? from unicode to ASCII or from utf-8 to ASCII???
could you let me know if you know about this???
Messages are transmitted as utf-8. See section 5.6 of the spec for details.
Its up to you what encoding you use within your server. UTF-8 is easy to handle in C (it is still terminated by single nul character so all string functions work) so you might find it easiest to use UTF-8 in your code and not convert to ascii/unicode.

not able to call methods after decoding from json

I have a Lua class like below. I am using json to serialize the object and put it in a key value store. I am able to serialize the object and put it in the key value store successfully but i am not able to call any methods of the object after i retrieve the object from the key value store. I understand the json module skips the methods while encoding and my object does not have methods after decoding.
Is there a way to append methods to the class after i decode the object from json to lua ? some thing similar to function pointers in C language.
local class_name = "user_object";
user_object = {}; --user class
function user_object.new (mobile, password, uid)
local self = {};
self.mobile = mobile;
self.uid = uid; -- generate a uid which is a running number.
self.password = password;
self.messages_sent = 0;
self.put_request_count = 0;
self.get_request_count = 0;
self.last_time_active = "";
self.get_tickets = {};
self.put_tickets = {};
self.group_message_stream = {};
self.group_ownerships = {}; -- group names which he is owner of
self.group_memberships = {}; -- group names which he is member of
self.sent_poke_count = 0;
self.sent_poke_stream = {};
self.recv_poke_count = 0;
self.recv_poke_stream = {};
function self:add_put_ticket(ticketid)
table.insert(self.put_tickets, ticketid);
self:incr_put_count();
self:save();
return;
end
function self:add_get_ticket(ticketid)
table.insert(self.get_tickets, ticketid);
self:incr_get_count();
self:save();
return;
end
Function in Lua are first class objects, you can store a function in any variable. The line
function self:add_put_ticket(ticketid)
is equivalent to
self.add_put_ticket = function (self, ticketid)
From there, it should be obvious what to do: define your desired methods where they are accessible and assign them to the appropriate fields after deserialization
You can do this with metatables.
user = { name = 'ponzao' } -- Just a table with values.
User = {} -- Table containing the functions.
function User:allCapsName() return self.name:upper() end -- A method.
setmetatable(user, {__index = User}) -- For unavailable keys all calls are dispatched to User.
print(user:allCapsName()) --> "PONZAO"