Javascript text encryption

For help and advice about coding

Moderator: Tech Moderators

User avatar
doogle
Posts: 783
Joined: Wed Mar 21, 2007 1:25 am
Tag: Likes squeezy cheesy cobs.
Location: Sherwood Forest
Contact:

Javascript text encryption

Postby doogle » Thu Jul 02, 2015 3:04 pm

Hi everybody. I have an old JavaScript encryption for a members area on my old website that I'm trying to get into. I have the code for all the bits other than the original plain text members.js file.

Does anybody know of a way to decrypt a code if you know the code and password it was encoded with?

This is the code used to create the hash values

Code: Select all

var alpha="1qazxsw23edcvfr€45tgbnhy67ujm,ki89ol./;p0-['#]=!QAZXSW£EDCVFR$%TGBNHY^&UJM<KI*(OL>?:P)_{@~}+`¬ ";

function makehash(str,mult){   // makehash("doogle",6);
   hash=0;   // Output
   for (j=0;j<str.length;j++) hash=hash*mult+alpha.indexOf(str.substring(j,j+1),0)+1; // Generate hash code, on first loop,
      // hash is 0 so hash*mult is also 0.
   return hash; // Return output
}

username = makehash("doogle",6);

username shows as 139402. What I'm wanting to do is take the '139402' and turn it back into 'doogle', but when I attempt to reverse the code, I'm at a loss as to how to get it to return text rather than numbers. Is it even possible?

This is the code to encrypt and decrypt the rest of the code that is encrypted with the hash codes created above...

Code: Select all

function encrypt(str,pass,enc){   // encrypt("username¬password¬etc","password hash","1");
   var sc="";   // Output value
   var cnt=0;   // counter
   if(str==null) return;   // No string passed, leave function
   for(k=0;k<str.length;k++){   // Loop through all characters in str
      c=str.substring(k,k+1);   // Grab current character from str
      a=alpha.indexOf(c);   // Grab position of this character in alpha string
         // (ie the letter 'e' is character 9 in the string)
      if(a>=0){   // Check if character exists in alpha string
         if(enc){   // Encode the string
            b=pass.substring(cnt,cnt+1)*1+a; // Grab first value from password hash and add
               // the position of the current character. The *1 just ensures it is a numerical value
            if(b>alpha.length-1) b=b-alpha.length; // Make sure that b stays within the bounds of the alpha string
         }else{   // Decode the string
            b=a-pass.substring(cnt,cnt+1); // Remove the first value of the password hash from the
               // position of the current character
            if(b<0) b=b+alpha.length; // Make sure that b stays within the bounds of the alpha string
         }
         if(b>alpha.length||b<0)   // There are either too many or too few characters in the resulting string
            alert("There has been an error with the encoding process.");
         c=alpha.substring(b,b+1);   // Replace the current character with one from the alpha string
         (cnt<pass.length)? cnt=cnt+1 : cnt=0;   // Check if counter has reached the password hash length, if not,
            // add 1 to it, otherwise reset it to 0.
      }
      sc+=c;   // Add this character to the final output, if the character doesn't exist in the alpha string, put it here in plain text.
   }
   return sc;   // Return output
}

User avatar
RB
Posts: 10687
Joined: Sun Mar 18, 2007 3:27 pm

Re: Javascript text encryption

Postby RB » Thu Jul 02, 2015 7:15 pm

I thought this was one way so the password entry is encrypted and compared to the stored encrypted password.
A slight majority of a statistically worthless sample size agree.

User avatar
Tinlad
Tech Moderator
Posts: 3345
Joined: Sun Mar 18, 2007 4:54 pm
Tag: Dog food scientist.
Location: Leeds
Contact:

Re: Javascript text encryption

Postby Tinlad » Fri Jul 03, 2015 12:05 pm

Indeed, one of the key ideas behind encryption is the concept of functions that are very difficult/impossible to reverse. I'm sure Savara will be able to explain in infinitely more depth!

That said, the makehash() function is pretty weak. If you know the value of mult then it's relatively easy to find the set of inputs (i.e. usernames) that correspond to any given hash. There will be a lot of possible inputs per hash, but if you have a list of usernames that you're looking for you could just search with those to find out which is the right one.

User avatar
Savara
Posts: 2071
Joined: Sun Sep 23, 2007 5:45 pm
Location: London
Contact:

Re: Javascript text encryption

Postby Savara » Sat Jul 04, 2015 7:01 pm

Yup; the point of a hash is certainly that it's ideally a one way function, i.e. it's very computationally easy to take the hash of x, but it's computationally infeasible (or the fastest way to do it is brute force all possible inputs) to work out what x is if you've got the hash of it.

Having had a 30 second look at the code I'm not quite sure what it's doing, nor that they're even half decent hash / encryption functions, so I might have a fiddle with it: if I get anywhere I'll post back. No promises!

User avatar
Blak
Tech Moderator
Posts: 1759
Joined: Mon Mar 19, 2007 12:07 pm
Tag: Hasn't realised that there are custom ranks yet
Contact:

Re: Javascript text encryption

Postby Blak » Sun Jul 05, 2015 11:42 pm

Evenin' folks. Long time no see and all that. This caught my eye. Proper hashing functions make use of multiplying prime numbers together in a way that is isn't feasible to work out the original constituent numbers. This usage of prime numbers also makes finding collisions (two passwords that generate the same end value) very unlikely. This function however, really REALLY doesn't do that - thanks to this "hash" function using multiplication and addition of non-primes it means there's loads of collision values!

I've made a thing to find collisions

Source here for the sake of it:

Code: Select all

// Somebody asked for help reversing a "hashing" function as they've got a list of hashes, but no passwords
// Of course if it was a proper hashing function then you'd be stuffed and the only way to do it would be rainbow tables.
// Entertainingly the hashing function they provided as flawed as all hell so we can build something that shall easily generate collisions - multiple passwords that generate the same "hash".

// The original encoding cipher
var alpha="1qazxsw23edcvfr€45tgbnhy67ujm,ki89ol./;p0-['#]=!QAZXSW£EDCVFR$%TGBNHY^&UJM<KI*(OL>?:P)_{@~}+`¬ ";

// The original "hash" function
// Ignore the bad style where they're using a global variable and using str.substring where str.charAt would be better...
function makehash(str,mult){   // makehash("doogle",6);
   hash=0;   // Output
   for (j=0;j<str.length;j++) hash=hash*mult+alpha.indexOf(str.substring(j,j+1),0)+1; // Generate hash code, on first loop,
      // hash is 0 so hash*mult is also 0.
   return hash; // Return output
}

///////////////////////
// Let's get reversing!
///////////////////////

// Build a reverse lookup table for the cipher key.
// In the original it was based off the character's position in the string (1 = 1, q = 2, a = 3) etc.
// This function builds out an inverse of that as we want to be working backwards
function createAlphaLooup(input) {
  var result = {};

  for (var i in input) {
    result[input[i]] = i;
  }

  return result;
}

// The original has function is flawed in such a way, that you can determine valid final characters for a password for a given "hash".
function potentialFinalCharacter(hash, mult, lookupTable) {
  var newhash;
  for (var char in lookupTable) {
    newhash = (hash - 1 - lookupTable[char]) / (mult);
    // Valid values are integers greater than or equal to 0
    // There is usually loads of these per hash, but we only care about the first one as we want to find /any/ collision, not all of them
    if (newhash >= 0 && newhash % 1 === 0) {
      return [newhash, char];
    }
  }
 
  throw "Couldn't find a character for that hashkey, You've entered an invalid starting hash"
}

// Finding a collision is a case of reducing the inital "large" hash down to a smaller "hash" (Saving the letter we expect to see at the end), then repeating that process till the "hash" is equal to 0, which means we've found our collision
function findCollision(initialHash, mult, alpha) {
  var lookupTable = createAlphaLooup(alpha);
  var chars = [];
  var hash = initialHash;
 
  do {
    result = potentialFinalCharacter(hash, mult, lookupTable);
   
    hash = result[0];
    chars.push(result[1]);
 } while(hash > 0);
 
  return chars.reverse().join('');
}


// Should be 139402
var originalPassword ='doogle';
var originalHash = makehash(originalPassword,6);

var collisionPassword = findCollision(originalHash, 6, alpha);
var collisionedHash = makehash(collisionPassword,6);

document.write('Original Password: ' + originalPassword + '<br>');
document.write('Original Hash: ' + originalHash + '<br>');

document.write('Collision Password: ' + collisionPassword + '<br>');
document.write('Collision Hash: ' + collisionedHash + '<br>');

document.write('Collision Hashes are EQUAL: ' + (originalHash == collisionedHash ) + '<br>');

User avatar
Tinlad
Tech Moderator
Posts: 3345
Joined: Sun Mar 18, 2007 4:54 pm
Tag: Dog food scientist.
Location: Leeds
Contact:

Re: Javascript text encryption

Postby Tinlad » Tue Jul 07, 2015 10:12 am

Nice. :geek:

I started writing a script to find all solutions using the same basic method, but didn't finish it (as I haven't used JS in ages and was having to relearn it as I went along :oops:).

I think you can create a collision for any hash with only the first mult characters in the character list, as there'll always be an integer factor within that group.

'qxxaq1z' collides with 'doogle'.

User avatar
Ekona
Posts: 16607
Joined: Sun Mar 18, 2007 8:24 pm
Tag: Official member of the RB Anti Facist Party est. 2009
Location: Braintree, innit

Re: Javascript text encryption

Postby Ekona » Tue Jul 07, 2015 12:24 pm

I can understand the gist of most things on the interweb. This though... Nope, miles out. :lol:
"Chav kids are like sand people. They're easily startled but they'll be back, and in greater numbers."

User avatar
doogle
Posts: 783
Joined: Wed Mar 21, 2007 1:25 am
Tag: Likes squeezy cheesy cobs.
Location: Sherwood Forest
Contact:

Re: Javascript text encryption

Postby doogle » Wed Jul 08, 2015 4:18 pm

Thanks for this, I didn't think it would be possible to reverse it. I'll have to dig around my old HDDs to find the original files with the unencoded lists.

That was a cool little thingy you made there Blak. I'll look into making a better encoding thingy to avoid the collisions, I didn't write the original code but I can only find one reference to it on the Internet now, and that is on an old, un-used angelfire website.

User avatar
Tinlad
Tech Moderator
Posts: 3345
Joined: Sun Mar 18, 2007 4:54 pm
Tag: Dog food scientist.
Location: Leeds
Contact:

Re: Javascript text encryption

Postby Tinlad » Wed Jul 08, 2015 5:27 pm

This area is one in which, unless you're an absolute expert in it, you shouldn't try to roll your own solution. The maths behind creating good hash functions is pretty intense (and I'm not claiming to have any understanding of it either!).

There are plenty of hashing algorithms available (e.g. SHA-1, MD5) that would do the job perfectly well.

User avatar
Tinlad
Tech Moderator
Posts: 3345
Joined: Sun Mar 18, 2007 4:54 pm
Tag: Dog food scientist.
Location: Leeds
Contact:

Re: Javascript text encryption

Postby Tinlad » Wed Jul 08, 2015 6:08 pm

Here's my edit of Blak's code, which uses a mathematical approach to finding collisions. Key difference is this:

Code: Select all

function potentialFinalCharacter(hash, mult) {
  var newhash, charnum, char;
 
  charnum = (hash - 1)%mult;
  newhash = (hash - 1 - charnum)/mult;
  char = alpha[charnum];
 
  return [newhash, char];
}


It isn't necessary to check all characters and see if they create an integer solution; instead we can go straight to the simplest answer which is the remainder of the hash (minus 1) divided by the multiplier!

User avatar
doogle
Posts: 783
Joined: Wed Mar 21, 2007 1:25 am
Tag: Likes squeezy cheesy cobs.
Location: Sherwood Forest
Contact:

Re: Javascript text encryption

Postby doogle » Fri Jul 10, 2015 1:27 pm

Oh, it's only a members area for my personal website, nothing important or confidential in there.


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 1 guest

cron