patterncppMinor
Perform SHA-256 on input
Viewed 0 times
inputperformsha256
Problem
This code is intended to take input as a string, do a SHA-256 hash on the string, and return the result.
It works correctly for the standard test vectors (test code included at the bottom). I'm particularly interested in your thoughts about whether it would be a good idea for it to accept input in forms other than a string (e.g., be able to work directly with a
Another possibility that has occurred to me (but I'm not sure if it's worthwhile) would be to have it accept a pair of iterators. The (somewhat) unusual part about that is that even though we don't care about the form of the source, we do care about assuring that the iterator's value_type is
First the header:
```
// sha256.h
#ifndef SHA_256_H_INCLUDED
#define SHA_256_H_INCLUDED
// This is a relatively straightforward implementation of SHA-256. It makes no particular
// attempt at optimization, instead aiming toward easy verification against the standard.
// To that end, many of the variable names are identical to those used in FIPS 180-2 and
// FIPS 180-3.
//
// The code should be fairly portable, within a few limitations:
// 1. It requires that 'char' have 8 bits. In theory this is avoidable, but I don't think
// it's worth the bother.
// 2. It only deals with inputs in (8-bit) bytes. In theory, SHA-256 can deal with a number of
// bits that's not a multiple of 8, but I've never needed it. Since the padding always results
// in a byte-sized stream, the only parts that would need changing would be reading and padding
// the input. The main hashing portion would be unaffected.
//
// Originally written in February 2008 for SHA-1.
// Converted to SHA-256 sometime later (sorry, I don't remember exactly when).
//
// You can use this software any way you want to, with following limitations
// (shamelessly stolen from the Boost software license):
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLU
It works correctly for the standard test vectors (test code included at the bottom). I'm particularly interested in your thoughts about whether it would be a good idea for it to accept input in forms other than a string (e.g., be able to work directly with a
std::ifstream).Another possibility that has occurred to me (but I'm not sure if it's worthwhile) would be to have it accept a pair of iterators. The (somewhat) unusual part about that is that even though we don't care about the form of the source, we do care about assuring that the iterator's value_type is
char (or possibly a signed/unsigned variant).First the header:
```
// sha256.h
#ifndef SHA_256_H_INCLUDED
#define SHA_256_H_INCLUDED
// This is a relatively straightforward implementation of SHA-256. It makes no particular
// attempt at optimization, instead aiming toward easy verification against the standard.
// To that end, many of the variable names are identical to those used in FIPS 180-2 and
// FIPS 180-3.
//
// The code should be fairly portable, within a few limitations:
// 1. It requires that 'char' have 8 bits. In theory this is avoidable, but I don't think
// it's worth the bother.
// 2. It only deals with inputs in (8-bit) bytes. In theory, SHA-256 can deal with a number of
// bits that's not a multiple of 8, but I've never needed it. Since the padding always results
// in a byte-sized stream, the only parts that would need changing would be reading and padding
// the input. The main hashing portion would be unaffected.
//
// Originally written in February 2008 for SHA-1.
// Converted to SHA-256 sometime later (sorry, I don't remember exactly when).
//
// You can use this software any way you want to, with following limitations
// (shamelessly stolen from the Boost software license):
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLU
Solution
Virtual operator?
Personally I thinks this obfuscates the meaning and makes it harder to see that the call is using virtual dispatch (but that is just an opinion there is nothing technically wrong here).
I have a hard time following the logic here:
Also the comment does not accurately reflect what it does:
After decoding this I find that you are adding the length to the end. BUT the length takes it upto the 512 bit byte boundary. It is not added after the string has been padded.
I assume this:
Is trying to compensate for endianeess. I would rather see a standard function here. Something like
I assume there is a reason that the padding starts with: '\x80`. It would be nice that is in the comment. There must be a technical reason you are not '\0' padding the string.
I prefer to always use {} in sub-statements. That way my code looks consistent:
It always worries my bare statement inside an if. Especially with function calls that potentially look like macros.
struct ternary_operator {
virtual uint32_t operator()(uint32_t x, uint32_t y, uint32_t z) = 0;
};Personally I thinks this obfuscates the meaning and makes it harder to see that the call is using virtual dispatch (but that is just an opinion there is nothing technically wrong here).
I have a hard time following the logic here:
std::string sha256::pad(std::string const &input) {Also the comment does not accurately reflect what it does:
// Pad the input to a multiple of 512 bits, and add the length
// in binary to the end.After decoding this I find that you are adding the length to the end. BUT the length takes it upto the 512 bit byte boundary. It is not added after the string has been padded.
I assume this:
for (int i=sizeof(length)-1; i>-1; i--) {
unsigned char byte = length >> (i*8) & 0xff;
padding.push_back(byte);
}Is trying to compensate for endianeess. I would rather see a standard function here. Something like
htonl() or an equivalent.I assume there is a reason that the padding starts with: '\x80`. It would be nice that is in the comment. There must be a technical reason you are not '\0' padding the string.
std::string padding("\x80");
padding.append(std::string(k/8, '\0'));I prefer to always use {} in sub-statements. That way my code looks consistent:
for (int t=16; t<64; ++t)
W[t] = f6(W[t-2]) + W[t-7] + f5(W[t-15]) + W[t-16];It always worries my bare statement inside an if. Especially with function calls that potentially look like macros.
Code Snippets
struct ternary_operator {
virtual uint32_t operator()(uint32_t x, uint32_t y, uint32_t z) = 0;
};std::string sha256::pad(std::string const &input) {// Pad the input to a multiple of 512 bits, and add the length
// in binary to the end.for (int i=sizeof(length)-1; i>-1; i--) {
unsigned char byte = length >> (i*8) & 0xff;
padding.push_back(byte);
}std::string padding("\x80");
padding.append(std::string(k/8, '\0'));Context
StackExchange Code Review Q#13288, answer score: 4
Revisions (0)
No revisions yet.