nodejs md5 with base64 digest algorithm wrong result - node.js

here is my code
var sig = crypto.createHash('md5')
.update('The quick brown fox jumps over the lazy dog')
.digest('base64');
console.log(sig)
results in nhB9nTcrtoJr2B01QqQZ1g== (on Mac OS X).
I'm trying to generate the same signature from an ios app. The results are the same in objective c as in online converter sites: the string
The quick brown fox jumps over the lazy dog
converted to md5, I get
9e107d9d372bb6826bd81d3542a419d6,
and the base64 of this is OWUxMDdkOWQzNzJiYjY4MjZiZDgxZDM1NDJhNDE5ZDY=.
Why are those strings different? Isn't this what nodejs crypto module is doing?
What are the equivalent of nodejs algorithm for getting the md5 hash digested with base64?

The string OWUxMDdkOWQzNzJiYjY4MjZiZDgxZDM1NDJhNDE5ZDY= is the base64 encoded version of the string 9e107d9d372bb6826bd81d3542a419d6 which is in it self the md5 hash of the plain text string The quick brown fox jumps over the lazy dog.
If you want to do this in node you first have to get the md5 hash in hex:
var crypto = require('crypto');
var s = 'The quick brown fox jumps over the lazy dog';
var md5 = crypto.createHash('md5').update(s).digest('hex');
Now you have the md5 hash as hex (9e107d9d372bb6826bd81d3542a419d6). Now all you have to do is convert it to base64:
new Buffer(md5).toString('base64');

Related

CryptoJS with hex key not decrypting properly

I have a dataset that was encrypted that I'm trying to decrypt with CryptoJS. I've tried various combination of things but for some reason the result is not what I'm expecting. I have provided the key below and also the text I want to decrypt. What I'm expecting at msg1 is 32 characters long but I keep getting 48. Its as of its padding it with an extra 16 characters.
Thanks in advance for the help.
key = 'd13484fc2f28fd0426ffd201bbd2fe6ac213542d28a7ca421f17adc0cf234381';
text = '8bf3955488af91feb7bd87220910cee0';
decrypt(text: string): void{
let msg1 = CryptoJS.AES.decrypt(text, CryptoJS.enc.Hex.parse(key), { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding});
msg1 = CryptoJS.enc.Hex.stringify(msg1 );
}
Solving it is pretty simple, but reading the docs and the code, I'm not quite clear why.
This is clearly wrong:
let msg1 = CryptoJS.AES.decrypt(text, CryptoJS.enc.Hex.parse(key), { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding});
Given your description, you are expecting the byte sequence represented by the hex digits "8bf3955488af91feb7bd87220910cee0" to be the body. But that's not what your passing. You're passing the characters. So when it decrypts it, the first byte is the ASCII value of 8 (0x38), not 0x8b. Given that, you should be parsing the hex like this:
let msg1 = CryptoJS.AES.decrypt(CryptoJS.enc.Hex.parse(text), ...
But, for reasons I'm having trouble understanding, that doesn't work. decrypt expects Base64 (or at least it will accept Base64). I can't find any documentation that says this, and the code creates the decrypt function magically in a way that I don't fully understand, and this is why I really hate doing crypto work in JavaScript.
That's out of my system now, so let's get to the answer:
cipher = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Hex.parse(text))
let msg1 = CryptoJS.AES.decrypt(cipher, CryptoJS.enc.Hex.parse(key), { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding});
And that should give you the result you're expecting.
Given:
key = 'd13484fc2f28fd0426ffd201bbd2fe6ac213542d28a7ca421f17adc0cf234381';
text = '8bf3955488af91feb7bd87220910cee0';.
Decrypting the text with the key actually produces: C5640000B550000079320000217C0000.
See AES Calc
Verify the encoding that CryptoJS.AES.decrypt requires for it's inputs and output encoding.

How to encrypt in Node.js?

I'm attempting to perform encryption in Node.js 7.5.0 using the 'des-cbc' algorithm. According to RFC 1423, this algorithm requires a 64-bit cryptographic key, and a 64-bit initialization vector.
I'm trying to use a key and iv composed of 8 Latin-1 characters; however, Node is saying, "Error: Invalid IV length". Here's some example code:
let crypto = require('crypto');
let key = '\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8',
iv = '\xb8\xb7\xb6\xb5\xb4\xb3\xb2\xb1';
let cipher = crypto.createCipheriv('des-cbc', Buffer.from(key), Buffer.from(iv));
If I change the iv to 8 ASCII characters, then Node is saying, "Error: Invalid key length":
let crypto = require('crypto');
let key = '\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8',
iv = 'abcdefgh';
let cipher = crypto.createCipheriv('des-cbc', Buffer.from(key), Buffer.from(iv));
But if both the key and iv are 8 ASCII characters, it works:
let crypto = require('crypto');
let key = 'hgfedcba',
iv = 'abcdefgh';
let cipher = crypto.createCipheriv('des-cbc', Buffer.from(key), Buffer.from(iv));
Why can't the Latin-1 characters be used for key and iv?
Solution
You should either use
Buffer.from('\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8', 'binary')
or even more cleaner as Maarten Bodewes points out
Buffer.from([0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8'])
The same goes for your IV.
Reason
Buffer.from('\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8').length results in 16 which is not a valid length for a DES key. DES expects exactly 64 bits or 8 bytes as a key. That is also why DES is very insecure. The key size is simply too small.
The reason the above Buffer has a size of 16 bytes instead of 8 bytes is that the default encoding is UTF-8. If a code point is larger than 127 (decimal) or 0x7F (hexadecimal) it will encode into at least two bytes instead of one. Each and every code point (character) of your key is larger than 0x7F. So, each of them is encoded into two bytes.
Things to think about
Don't use DES nowadays. It only provides 56 bit of security. AES would be a much better, because it's more secure with the lowest key size of 128 bit. There is also a practical limit on the maximum ciphertext size with DES. See Security comparison of 3DES and AES.
The IV must be unpredictable (read: random). Don't use a static IV, because that makes the cipher deterministic and therefore not semantically secure. An attacker who observes ciphertexts can determine when the same message prefix was sent before. The IV is not secret, so you can send it along with the ciphertext. Usually, it is simply prepended to the ciphertext and sliced off before decryption.
The key is supposed to be indistinguishable from random noise. It is best to just generate it randomly and use it in your code in encoded form.
It is better to authenticate your ciphertexts so that attacks like a padding oracle attack are not possible. This can be done with authenticated modes like GCM or EAX, or with an encrypt-then-MAC scheme.

Node.js crypto key and iv to match java SecretKeySpec / IvParameterSpec

I'm trying to to port a Java (simple) encryption algorythm to Node JS. I will need to be able to decrypt/encrypt stuff encrypted/decrypted from the Java side.
I'm stuck at the very beginning, the initialization of the cipher.
In Java, I get the key with SecretKeySpec, and the Initialization Vector with IvParameterSpec:
public CryptStuff(String password) throws zillion_exceptions {
if (password==null) throw new InvalidKeyException("No encryption password is set!");
key = new SecretKeySpec(password.getBytes("UTF-8"), "AES");
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
ivSpec=new IvParameterSpec(new byte[cipher.getBlockSize()]);
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
}
NodeJS requires a Key Buffer and an IV buffer, however, I don't know how to calculate them from scratch:
var mCrypto = require('crypto'),
key=[0,0,0,0,0,0,.......],
iv=[0,0,0,0,0,.........];
function init (password) {
// generate key from password
// generate IV from blocksize?
var aesCipher = mCrypto.createCipheriv("aes-????????", (new Buffer(key)), (new Buffer(iv)));
.
.
.
}
Also, what's the matching algorithm string for AES/CBC/PKCS5Padding?
Assuming you have the same password string as in the Java code, you can create a key buffer like this in node:
var key = new Buffer(password, "utf8");
Since you're using a zero filled IV (bad!) in Java, this is the equivalent code in node:
var iv = new Buffer(16); // 16 byte buffer with random data
iv.fill(0); // fill with zeros
Since you're using CBC mode in Java, you have to do the same in node. Note that you have to select the correct key size when selecting the cipher string depending on your "password" length:
var aesCipher = mCrypto.createCipheriv("aes-128-cbc", key, iv);
// or
var aesCipher = mCrypto.createCipheriv("aes-192-cbc", key, iv);
// or
var aesCipher = mCrypto.createCipheriv("aes-256-cbc", key, iv);
Node will automatically apply PKCS#7 padding which is the same as PKCS#5 padding for AES.
A password is not a key!
A password has usually not the appropriate length to be used as a key (valid lengths are 16 byte, 24 byte and 32 byte for AES) and it is comprised of only printable characters which might make it easier for an attacker to brute force the key.
What you would need to create a key from a password is key derivation function. Popular ones are PBKDF2, bcrypt and scrypt (with increasing cost).
Random IV!
You really should be generating a new random IV for every ciphertext that you produce. If you use a static IV, an attacker that observes your ciphertexts can determine that you sent the same or even similar messages. If you use a random IV, then the ciphertexts differ so much that an attacker cannot determine whether two different ciphertexts where created from the same plaintext or not. This is called semantic security.
The random IV itself doesn't have to be secret, so you can easily prepend it to the ciphertext and slice it off before decryption.
You can even combine this with the key derivation function (KDF). Simply generate a random salt for the KDF. A KDF is usually able to derive a variable amount of output bytes, so simply let it derive key || IV (concatenation) and then split them. Now, you only need to prepend the salt to the ciphertext.
Authentication!
Depending on your system, you might be vulnerable to attacks such as the padding oracle attack. The best defense against this is to authenticate the ciphertext. So you can either use an encrypt-then-MAC scheme with a strong MAC such as HMAC-SHA256 or an authenticated mode of operation such as GCM or EAX. Java and node both support GCM, but there is a little more work involved.

AS3 - Remove a section of a string using the character index

I have a string, and I want to remove a specific section from it.
The situation is as follows:
var input:String = "The quick brown fox jumped over the lazy dog.";
var scrubStart:Number = input.indexOf("br");
var scrubEnd: Number = input.indexOf("la");
var output:String = input.substring(0,scrubStart) + input.substring(scrubEnd,input.length);
I have it set up like this because the input text is different every time, and the section I want to remove is in a different place every time, but the content of the section is the same.
The code I have doesn't work, and it returns everything after scrubStart. Where have I gone wrong?
Code from your question appears to operate as expected, resulting in:
The quick lazy dog.
This could be accomplished using string methods of either slice or substring.
Slice:
const input:String = "The quick brown fox jumped over the lazy dog.";
var output:String = input.slice(0, input.indexOf("br")) +
input.slice(input.indexOf("la"));
Substring:
const input:String = "The quick brown fox jumped over the lazy dog.";
var output:String = input.substring(0, input.indexOf("br")) +
input.substring(input.indexOf("la"));
Regex:
You could also implement regular expressions; although, by pattern instead of index.
const input:String = "The quick brown fox jumped over the lazy dog.";
var pattern:RegExp = /brown.*?the /;
var output:String = input.replace(pattern, "");

replace strings inside a substring

I have this string:
"The quick brown f0x jumps 0ver the lazy d0g, the quick brown f0x jumps 0ver the lazy d0g.".
I need a function that will replace all zeros between "brown" and "lazy" with "o". So the output will look like this:
"The quick brown fox jumps over the lazy d0g, the quick brown fox jumps over the lazy d0g.".
So it will look all over the string and most importantly will leave all other zeros intact.
function(text, leftBorder, rightBorder, searchString, replaceString) : string;
Is there any good algorithm?
If you have Python, here's an example using just string manipulation, eg split(), indexing etc. Your programming language should have these features as well.
>>> s="The quick brown f0x jumps 0ver the lazy d0g, the quick brown f0x jumps 0ver the lazy d0g."
>>> words = s.split("lazy")
>>> for n,word in enumerate(words):
... if "brown" in word:
... w = word.split("brown")
... w[-1]=w[-1].replace("0","o")
... word = 'brown'.join(w)
... words[n]=word
...
>>> 'lazy'.join(words)
'The quick brown fox jumps over the lazy d0g, the quick brown fox jumps over the lazy d0g.'
>>>
The steps:
Split the words on "lazy" to an array A
Go through each element in A to look for "brown"
if found , split on "brown" into array B. The part you are going to change is the
last element
replace it with whatever methods your programming language provides
join back the array B using "brown"
update this element in the first array A
lastly, join the whole string back using "lazy"

Resources