How to calculate a 256-bit HMAC_SHA3 hash with CryptoJS? - hash

Recent CryptoJS versions support SHA3 hashing.
SHA3 can output different hash sizes, including 512-bit (default) and 256-bit. These two work fine:
var sha3_512_hash = CryptoJS.SHA3( 'test' );
var sha3_256_hash = CryptoJS.SHA3( 'test' , { outputLength:256 } );
Similarly, CryptoJS can also calculate HMAC values. However, I can't figure out how to change the default output size there:
var sha3_512_hmac = CryptoJS.HmacSHA3( 'test' , 'key' );
var sha3_256_hmac = CryptoJS.HmacSHA3( 'test' , 'key' , { outputLength:256 } );
The first works OK (the result is a 512-bit hmac value) but the second is the same (i.e. also 512-bit), as if it ignores the {outputLength:256} parameter!
Here's a live example: http://jsfiddle.net/M8xf3/ (using hmac-sha3.js from CryptoJS 3.1.2)
Does anyone know how to create 256-bit SHA3-based HMAC hashes?
P.S. For the SHA2 family of functions, CryptoJS has separate Hmac functions for each output size (that's HmacSHA256 and HmacSHA512). But this doesn't seem to be the case for SHA3?

This doesn't answer the actual question, but note that with SHA3 you don't really need HMAC hashes. Unlike SHA1 and SHA2 and MD5, SHA3 is not vulnerable to length-extension attacks.
Therefore with SHA3 it would suffice to just prepend or append the secret key to your input.
Or, if you're paranoid of a single hash step becoming compromised (not to be expected in the foreseeable future, especially not with SHA3, but still) you could do something like SHA3(key+SHA3(key+data)) or SHA3(key+SHA3(key+data)+data) (obviously with "+" denoting binary concatenation).

You can just edit hmac-sha3.js and change the outputLength to 256-bit instead of 512-bit.
Open hmac-sha3.js file, using your text editor.
Find "{outputLength:512}" and replace it with "{outputLength:256}"
Then the hash output will be 256-bit in length.
To be sure that you did not messed up things, double check your 256-bit hmac-sha3 output with some test cases available on the internet, for example: http://www.di-mgt.com.au/hmac_sha3_testvectors.html

Related

Question about Crypt::OpenSSL::RSA->verify method

My question is about this:
https://metacpan.org/pod/Crypt::OpenSSL::RSA
If there described method verify() fails, I do error handling like this:
my $rsa_pub = Crypt::OpenSSL::RSA->new_public_key($x509PubKey);
logm("exception: my err msg...") unless $rsa_pub->verify($text, $signature);
But is it possible get exact reason why verification failed?
I'm not sure that getting "the exact reason why verification failed" makes sense as a question. To verify a signature you specify:
the signature algorithm
the padding algorithm
the hashing function
Ultimately the signature is just a number that was computed by padding the the plaintext input, hashing the resulting bytes and performing a mathematical calculation using the private key.
Verifying the signature involves taking the plaintext, padding it, hashing it, and performing a mathematical calculation using the public key to produce another number which is then compared to the number from the signature (using modulo arthimetic?). If the numbers are the same then the signature is valid if they're different, it's not.
All of which is a roundabout way of saying if the verify method returns false then assuming you're using the correct public key, one of these things must be different:
the plaintext
the signature algorithm
the padding algorithm
the hashing function
But there's really no way of knowing which. It's like saying "I'm trying to multiply two numbers to get 42, but I don't get 42, which of the numbers is wrong?".
Here are a couple of signature verification functions for common combinations of algorithms (which I wrote for Authen::NZRealMe::XMLSig):
sub _verify_signature_rsa_sha1 {
my($self, $plaintext, $bin_sig) = #_;
my $rsa_pub_key = Crypt::OpenSSL::RSA->new_public_key($self->pub_key_text);
$rsa_pub_key->use_pkcs1_padding();
$rsa_pub_key->use_sha1_hash();
return $rsa_pub_key->verify($plaintext, $bin_sig);
}
sub _verify_signature_rsa_sha256 {
my($self, $plaintext, $bin_sig) = #_;
my $rsa_pub_key = Crypt::OpenSSL::RSA->new_public_key($self->pub_key_text);
$rsa_pub_key->use_pkcs1_oaep_padding();
$rsa_pub_key->use_sha256_hash();
return $rsa_pub_key->verify($plaintext, $bin_sig);
}
The context for the above code is signed sections of XML documents, which has the added complexity of needing to use the right canonicalization and encoding and also the signature data is Base64 encoded so needs to be decoded into bytes first.
The information about which padding and hashing algorithms to use should be available from the spec for the source data you're working with, but if not I guess you could try random combinations.

Get Matching SHA256 Algorithm - Perl

Hi I'm trying to generate a similar sha256 hex, but I can't seem to get a matching one. I want to generate just about any password using a random key.
In this case, I'm using test123 : ecd71870d1963316a97e3ac3408c9835ad8cf0f3c1bc703527c30265534f75ae
Here is my code:
print "Final Hash: " . generateHash("ecd71870d1963316a97e3ac3408c9835ad8cf0f3c1bc703527c30265534f75ae", "fx4;)#?%") . chr(10);
sub generateHash {
my ($strPass, $strLoginKey) = #_;
my $strHash = encryptPass(uc($strPass), $strLoginKey);
return $strHash;
}
sub encryptPass {
my ($strPassword, $strKey) = #_;
my $strSalt = 'Y(02.>\'H}t":E1';
my $strSwapped = swapSHA($strPassword);
print "First Swap: " . $strSwapped . chr(10);
my $strHash = sha256_hex($strSwapped . $strKey . $strSalt);
print "Hashed Into: " . $strHash . chr(10);
my $strSwappedHash = swapSHA($strHash) . chr(10);
print "Last Swapped: " . $strSwappedHash . chr(10);
return $strSwappedHash;
}
sub swapSHA {
my ($strHash) = #_;
my $strSwapped = substr($strHash, 32, 32);
$strSwapped .= substr($strHash, 0, 32);
return $strSwapped;
}
Any help would be greatly appreciated!
The output I get:
Original Hash: ecd71870d1963316a97e3ac3408c9835ad8cf0f3c1bc703527c30265534f75ae
Hashed Into: 34b6bdd73b3943d7baebf7d0ff54934849a38ee09c387435727e2b88566b4b85
Last Swapped: 49a38ee09c387435727e2b88566b4b8534b6bdd73b3943d7baebf7d0ff549348
Final Hash: 34b6bdd73b3943d7baebf7d0ff54934849a38ee09c387435727e2b88566b4b85
I am trying to make the output have final value same as input
Final Hash: ecd71870d1963316a97e3ac3408c9835ad8cf0f3c1bc703527c30265534f75ae
and I want to do this by reversing the "Hashed Into" value.
SHA, as a hashing algorithm, is designed to prevent collisions. i.e. part of its power, and usefulness, is in limiting the strings which will hash to the same resultant value.
It sounds like you want to find a second string which will hash to the same hashed value as test123 hashes to. This kind of goes the intent of using SHA in the first place.
It is possible to brute force the values with SHA, i.e. given a hashed value, you can brute force the value that was hashed by computing hashes and comparing the hashed value to the target value. This will take some time. Other algorithms, such as bcrypt, are more difficult to brute force, but are more computationally expensive for you also.
Here is another post related to brute forcing SHA-512, which is effectively equivalent in algorithm to SHA-256. The linked post is Java as opposed to Perl, but the concepts are language agnostic. How long to brute force a salted SHA-512 hash? (salt provided)
You're badly misunderstanding what a hash is for. It's a ONE WAY street by design. It's also designed to have a very low probability of 'collision' - two source values that hash to the same result. And by 'very low' I mean 'for practical purposes, it doesn't'. A constrained string - such as a password - simply won't do it.
So what typically happens for passwords - my client takes my password, generates a hash, sends it to the server.
The server compares that against it's list - if the hash matches, we assume that my password was correct. This means at no point is my password sent 'in the clear' nor is possible to work out what it was by grabbing the hash.
To avoid duplicates showing up (e.g. two people with the same password) usually you'll hash some unique values. Simplistically - username + password, when hashed.
The purpose of authenticating against hashes, is to ensure the cleartext password is never required to be held anywhere - and that is all. You still need to secure you communication channel (to avoid replay attacks) and you still need to protect against brute force guessing of password.
But brute forcing hashes is by design an expensive thing to attempt. You will see places where 'rainbow tables' exist, where people have taken every valid password string, and hashed it, so they can rapidly crack retrieved hashes from the server. These are big, and took a long time to generate initially though, and are defeated at least partially by salting or embedding usernames into the hash.
But I cannot re-iterate strongly enough - don't ever hand roll your own security unless you're REALLY sure what's going on. You'll build in weaknesses that you didn't even know existed, and your only 'security' is that no one's bothered to look yet.
You should not do this. It is insecure and vulnerable to dictionary attacks.
The correct way to turn passwords into things you store, is to use a PBKDF like "bcrypt" (password-based-key-derivation-function).
Check out Digest::Bcrypt
Word of caution: if anyone ever tells you (or helps you) to use a "hash" for storing passwords, they do not know anything about security or cryptography. Smile at them, and ignore everything they say next.

How do you use SHA256 to create a token of key,value pairs and a secret signature?

I want to validate some hidden input fields (to make sure they arent changed on submission) with the help of a sha-encoded string of the key value pairs of these hidden fields. I saw examples of this online but I didnt understand how to encode and
decode the values with a dynamic secret value. Can someone help me understand how to do this in perl?
Also which signature type (MD5, SHA1, SHA256, etc), has a good balance of performance and security?
update
So, how do you decode the string once you get it encoded?
What you really need is not a plain hash function, but a message authentication code such as HMAC. Since you say you'd like to use SHA-256, you might like HMAC_SHA256, which is available in Perl via the Digest::SHA module:
use Digest::SHA qw(hmac_sha256_base64);
my $mac = hmac_sha256_base64( $string, $key );
Here, $key is an arbitrary key, which you should keep secret, and $string contains the data you want to sign. To apply this to a more complex data structure (such as a hash of key–value pairs), you first need to convert it to a string. There are several ways to do that; for example, you could use Storable:
use Storable qw(freeze);
sub pairs_to_string {
local $Storable::canonical = 1;
my %hash = #_;
return freeze( \%hash );
}
You could also URL-encoding, as suggested by David Schwartz. The important thing is that, whatever method you use, it should always return the exact same string when given the same hash as input.
Then, before sending the data to the user, you calculate a MAC for them and include it as an extra field in the data. When you receive the data back, you remove the MAC field (and save its value), recalculate the MAC for the remaining fields and compare it to the value you received. If they don't match, someone (or something) has tampered with the data. Like this:
my $key = "secret";
sub mac { hmac_sha256_base64( pairs_to_string(#_), $key ) }
# before sending data to client:
my %data = (foo => "something", bar => "whatever");
$data{mac} = mac( %data );
# after receiving %data back from client:
my $mac = delete $data{mac};
die "MAC mismatch" if $mac ne mac( %data );
Note that there are some potential tricks this technique doesn't automatically prevent, such as replay attacks: once you send the data and MAC to the user, they'll learn the MAC corresponding to the particular set of data, and could potentially replace the fields in a later form with values saved from an earlier form. To protect yourself against such attacks, you should include enough identifying information in the data protected by the MAC to ensure that you can detect any potentially harmful replays. Ideally, you'd want to include a unique ID in every form and check that no ID is ever submitted twice, but that may not always be practical. Failing that, it may be a good idea to include a user ID (so that a malicious user can't trick someone else into submitting their data) and a form ID (so that a user can't copy data from one form to another) and perhaps a timestamp and/or a session ID (so that you can reject old data) in the form (and in the MAC calculation).
I don't know what you mean by "unpack", but you can't get original string from the hash.
Let's understand the problem: you render some hidden fields and you want to make sure that they're submitted unchanged, right? Here's how you can ensure that.
Let's suppose you have two variables:
first: foo
second: bar
You can hash them together with a secret key:
secret_key = "ysEJbKTuJU6u"
source_string = secret_key + "first" + "foo" + "second" + "bar"
hash = MD5(source_string)
# => "1adfda97d28af6535ef7e8fcb921d3f0"
Now you can render your markup:
<input type="hidden" name="first" value="foo" />
<input type="hidden" name="second" value="bar" />
<input type="hidden" name="hash" value="1adfda97d28af6535ef7e8fcb921d3f0">
Upon form submission, you get values of first and second fields, concat them to your secret key in a similar manner and hash again.
If hashes are equal, your values haven't been changed.
Note: never render secret key to the client. And sort key/value pairs before hashing (to eliminate dependency on order).
( disclaimer: I am not a crypto person, so you may just stop reading now)
As for performance/security, even though MD5 was found to have a weakness, it's still pretty usable, IMHO. SHA1 has a theoretical weakness, although no successful attack has been made yet. There are no known weaknesses in SHA-256.
For this application, any of the encryption algorithms is fine. You can pack the values any way you want, so long as it's repeatable. One common method is to pack the fields into a string the same way you would encode them into a URL for a GET request (name=value).
To compute the hash, create a text secret that can be whatever you want. It should be at least 12 bytes long though. Compute the hash of the secret concatenated with the packed fields and append that onto the end.
So, say you picked MD5, a secret of JS90320ERHe2 and you have these fields:
first_name = Jack
last_name = Smith
other_field = 7=2
First, URL encode it:
first_name=Jack&last_name=Smith&other_field=7%3d=2
Then compute the MD5 hash of
JS90320ERHe2first_name=Jack&last_name=Smith&other_field=7%3d=2
Which is 6d0fa69703935efaa183be57f81d38ea. The final encoded field is:
first_name=Jack&last_name=Smith&other_field=7%3d=2&hash=6d0fa69703935efaa183be57f81d38ea
So that's what you pass to the user. To validate it, remove the hash from the end, compute the MD5 hash by concatenating what's left with the secret, and if the hashes match, the field hasn't been tampered with.
Nobody can compute their own valid MD5 because they don't know to prefix the string with.
Note that an adversary can re-use any old valid value set. They just can't create their own value set from scratch or modify an existing one and have it test valid. So make sure you include something in the information so you can verify that it is suitable for the purpose it has been used.

Is Perl Data::UUID a strong symmetric key source?

I'm considering using Data::UUID Perl module to generate a 256 bit symmetric key for use with the HMAC_SHA256 algorithm. Each call should give me a unique string of 128 bits so I'm thinking of doing something like the following:
use Data::UUID;
my $ug = new Data::UUID;
my $uuid1 = $ug->to_hexstring($ug->create());
my $uuid2 = $ug->to_hexstring($ug->create());
my $256_bit_key = $uuid1 . $uuid2;
Is this key cryptographically strong?
No.
Use Crypt::OpenSSL::Random or another crypto-strong random number generator.
To be more precise, you can get some bytes from the CRNG, convert them into an ASCII string, and then use that to do the hash against.

MD5 file hash for the same unchanged file is different each time C#

Good evening all,
I've been working on an MD5 tool in C# that takes a file, goes through my Hasher class and pops the result in a database, along with the filename and directory.
The issue I'm having is that each time I run the test, the MD5 result for the same identical file i.e. unchanged in any way is completely different.
Below is the code I use
HashAlgorithm hmacMd5 = new HMACMD5();
byte[] hash;
try
{
using (Stream fileStream = new FileStream(fileLocation, FileMode.Open))
{
using (Stream bufferedStream = new BufferedStream(fileStream, 5600000))
{
hash = hmacMd5.ComputeHash(bufferedStream);
foreach (byte x in hash)
{
md5Result += x;
}
}
}
}
catch (UnauthorizedAccessException uae) { }
return md5Result;
Here are the results for 3 seperate runs of hello.mp2:
1401401571161052548110297623915056204169177
16724366215610475211823021169211793421
56154777074212779619017828183239971
Quite puzzling.
My only rational thought as to why I'm getting these results is with concatenating byte to string.
Can anyone spot an issue here?
Regards,
Ric
You should use System.Security.Cryptography.MD5 rather.
HMACMD5 doesn't compute a hash, it computes a message authentication code.
HMACMD5 is a type of keyed hash
algorithm that is constructed from the
MD5 hash function and used as a
Hash-based Message Authentication Code
(HMAC). The HMAC process mixes a
secret key with the message data,
hashes the result with the hash
function, mixes that hash value with
the secret key again, then applies the
hash function a second time. The
output hash will be 128 bits in length
Since you're not supplying the HMAC key, one is being generated randomly for you on your behalf and causing you to see different results.
My suggestion is that you are not computing MD5 hashes since MD5 produces a fixed length output of 32 hex numbers
Also, since you don't see any numbers from 0xA to 0xF is quite puzzling
You might wanna check a "real" result with online MD5 calculators such as this one
You shouldn't have a bufferedStream in between. I would guess a different number of bytes is buffered in each run.