Everytime I need to use the Crypto module, a great wave of anxiety sweeps over me. For most common programmers the case is usually that you need to MD5 or SHA256 som some data to send over HTTP to some REST API or something like that, or compare something to a hash stored in a database or something like that.
I had to make HMAC-SHA256 hash yesterday and it took me like 1,5 hours to figure that stuff out:
String.string2hex(Crypto.HMAC(Crypto.SHA256)(secret)(data));
Not the most intuitive stuff if you ask me.
That led me to the question: Why aren't there any helper methods directly in Crypto, for the more common use cases? So I've been fiddling around with it some and though that maybe something like below could be nice to have. This is just a mockup so feel free to point out if there are better ways to write the code, and if this is something that would fit at all.
//! Typedef for a generic hashing function that takes a string as argument //! and returnes a hashed and @[String.string2hex]'ed string. typedef function(string(8bit):string(8bit)) hash_func_t;
//! Typedef for a generic HMAC hash function that takes data and a secret as //! arguments and returns a hashed and @[String.string2hex]'ed string typedef function(string(8bit),string(8bit):string(8bit)) hash_hmac_func_t;
protected hash_func_t make_hash_func(Crypto.Hash hash, void|bool raw) { return lambda (string in) { string s = hash->hash(in); return raw ? s : String.string2hex(s); }; }
protected hash_hmac_func_t make_hash_hmac_func(Crypto.Hash hash, void|bool raw) { return lambda (string data, string secret) { string s = Crypto.HMAC(hash)(secret)(data); return raw ? s : String.string2hex(s); }; }
//! Create a HMAC hash of @[data] and @[secret] using the Crypto module @[hash]. //! //! @param hash //! @param data //! @param secret string hash_hmac(Crypto.Hash hash, string data, string secret) { return make_hash_hmac_func(hash)(data, secret); }
//! Creates a HMAC hashing function using the Crypto module @[hash]. This can //! later be called with the data and secret to make a hash of. //! //! @returns //! @tt{function(string, string : string)@} variant hash_hmac_func_t hash_hmac(Crypto.Hash hash) { return make_hash_hmac_func(hash); }
//! Creates a hash of @[data] using the hashing algorithm in @[hash]. //! If @[raw] is given the hash will not pass through @[String.string2hex]. string hash(Crypto.Hash hash, string data, void|bool raw) { return make_hash_func(hash, raw)(data); }
//! Creates a hashing function using the Crypto module @[hash]. This can later //! be called with the data to make a hash of. //! If @[raw] is given the hash will not pass through @[String.string2hex]. //! //! @returns //! @tt{function(string : string)@} variant hash_func_t hash(Crypto.Hash hash, void|bool raw) { return make_hash_func(hash, raw); }
hash_hmac_func_t hmac_sha256 = hash_hmac(Crypto.SHA256); hash_hmac_func_t hmac_md5 = hash_hmac(Crypto.MD5); hash_func_t md5 = hash(Crypto.MD5); hash_func_t sha256 = hash(Crypto.SHA256);
int main(int argc, array(string) argv) { string data = "my data"; string secret = "abc123";
write("%-20s %s\n", "hash_hmac(MD5):", hash_hmac(Crypto.MD5, data, secret)); write("%-20s %s\n", "hash_hmac_md5:", hmac_md5(data, secret)); write("%-20s %s\n", "hash_hmac_sha256:", hmac_sha256(data, secret)); write("%-20s %s\n", "hash(md5):", hash(Crypto.MD5, data)); write("%-20s %s\n", "hash(md5:raw):", hash(Crypto.MD5, data, true)); write("%-20s %s\n", "md5:", md5(data)); write("%-20s %s\n", "sha256:", sha256(data));
return 0; }
Regards ----------------------------- Pontus Östlund Developer • Roxen AB +46 70-662 81 69
www.roxen.com http://www.roxen.com/ | twitter.com/roxen https://twitter.com/roxen
I’d be in favor of more helpers… I recently did a module for Joyent Manta storage, which uses SSH keys to perform HTTP Signatures. All of the basic support was there, it was just a matter of figuring out how and what to string together. So, there’s a bunch of code that could be contributed for reading ssh key files, making fingerprints, and creating signature headers.
While we’re talking about such things, it might be nice to have helpers for extracting usable bits from the various PEM encoded keys and certs so that they can be used with the crypto module. I know the webservers have this code but there are plenty of times when it’s been useful outside (and I seem to recall there being a new format of key popping up that the code I do have doesn’t support.)
For reference, here’s the file with a bunch of the key/signature stuff if it’s of interest:
https://bitbucket.org/hww3/public_storage_manta/raw/38327b39af2b3d78d3d5158b...
Bill
On Jul 20, 2017, at 9:08 AM, Pontus Östlund pontus@roxen.com wrote:
Everytime I need to use the Crypto module, a great wave of anxiety sweeps over me. For most common programmers the case is usually that you need to MD5 or SHA256 som some data to send over HTTP to some REST API or something like that, or compare something to a hash stored in a database or something like that.
I had to make HMAC-SHA256 hash yesterday and it took me like 1,5 hours to figure that stuff out:
String.string2hex(Crypto.HMAC(Crypto.SHA256)(secret)(data));
Not the most intuitive stuff if you ask me.
That led me to the question: Why aren't there any helper methods directly in Crypto, for the more common use cases? So I've been fiddling around with it some and though that maybe something like below could be nice to have. This is just a mockup so feel free to point out if there are better ways to write the code, and if this is something that would fit at all.
//! Typedef for a generic hashing function that takes a string as argument //! and returnes a hashed and @[String.string2hex]'ed string. typedef function(string(8bit):string(8bit)) hash_func_t;
//! Typedef for a generic HMAC hash function that takes data and a secret as //! arguments and returns a hashed and @[String.string2hex]'ed string typedef function(string(8bit),string(8bit):string(8bit)) hash_hmac_func_t;
protected hash_func_t make_hash_func(Crypto.Hash hash, void|bool raw) { return lambda (string in) { string s = hash->hash(in); return raw ? s : String.string2hex(s); }; }
protected hash_hmac_func_t make_hash_hmac_func(Crypto.Hash hash, void|bool raw) { return lambda (string data, string secret) { string s = Crypto.HMAC(hash)(secret)(data); return raw ? s : String.string2hex(s); }; }
//! Create a HMAC hash of @[data] and @[secret] using the Crypto module @[hash]. //! //! @param hash //! @param data //! @param secret string hash_hmac(Crypto.Hash hash, string data, string secret) { return make_hash_hmac_func(hash)(data, secret); }
//! Creates a HMAC hashing function using the Crypto module @[hash]. This can //! later be called with the data and secret to make a hash of. //! //! @returns //! @tt{function(string, string : string)@} variant hash_hmac_func_t hash_hmac(Crypto.Hash hash) { return make_hash_hmac_func(hash); }
//! Creates a hash of @[data] using the hashing algorithm in @[hash]. //! If @[raw] is given the hash will not pass through @[String.string2hex]. string hash(Crypto.Hash hash, string data, void|bool raw) { return make_hash_func(hash, raw)(data); }
//! Creates a hashing function using the Crypto module @[hash]. This can later //! be called with the data to make a hash of. //! If @[raw] is given the hash will not pass through @[String.string2hex]. //! //! @returns //! @tt{function(string : string)@} variant hash_func_t hash(Crypto.Hash hash, void|bool raw) { return make_hash_func(hash, raw); }
hash_hmac_func_t hmac_sha256 = hash_hmac(Crypto.SHA256); hash_hmac_func_t hmac_md5 = hash_hmac(Crypto.MD5); hash_func_t md5 = hash(Crypto.MD5); hash_func_t sha256 = hash(Crypto.SHA256);
int main(int argc, array(string) argv) { string data = "my data"; string secret = "abc123";
write("%-20s %s\n", "hash_hmac(MD5):", hash_hmac(Crypto.MD5, data, secret)); write("%-20s %s\n", "hash_hmac_md5:", hmac_md5(data, secret)); write("%-20s %s\n", "hash_hmac_sha256:", hmac_sha256(data, secret)); write("%-20s %s\n", "hash(md5):", hash(Crypto.MD5, data)); write("%-20s %s\n", "hash(md5:raw):", hash(Crypto.MD5, data, true)); write("%-20s %s\n", "md5:", md5(data)); write("%-20s %s\n", "sha256:", sha256(data));
return 0; }
Regards
Pontus Östlund Developer • Roxen AB +46 70-662 81 69
www.roxen.com http://www.roxen.com/ | twitter.com/roxen https://twitter.com/roxen
Everytime I need to use the Crypto module, a great wave of anxiety sweeps over me. For most common programmers the case is usually that you need to MD5 or SHA256 som some data to send over HTTP to some REST API or something like that, or compare something to a hash stored in a database or something like that.
I had to make HMAC-SHA256 hash yesterday and it took me like 1,5 hours to figure that stuff out:
String.string2hex(Crypto.HMAC(Crypto.SHA256)(secret)(data));
The applications of the lower layer crypto is inherited into the implementations. I would do
String.string2hex(Crypto.SHA256.HMAC(secret)(data));
http://pike.lysator.liu.se/generated/manual/modref/ex/predef_3A_3A/Crypto/Ha...
pike-devel@lists.lysator.liu.se