[ ... ]
Thanks for the time. Sorry to keep dragging this out. I agree that
outputting to stream would offer more flexibility. I made it as is
because if the string of the hash (a "gettable value")is printed it
can contain non-printable characters...and I wanted the class to have
an in-built way to *display* itself to the user.
Separating "display" from "store" is perfectly fine, and irrelevant to
what I'm talking about here.
So...you'd advise
outputting the hex-formated output to a stringstream then pass that
back from the function as a string?
I suppose you could do that, but it's not what I had in mind at all. I
was thinking of something a bit simpler. Right now, showhex looks
roughly like this:
void HashS::showhex() {
std::cout << various_stuff;
}
I was talking about changing that to something like this:
void HashS::showhex(std:
stream os) {
os << various_stuff;
}
Makes sense but makes it slightly
harder to use, since the user would then have 2 different ways of
getting the hash...the displayable but not usable form, and the usable
but not displayable form. I was trying to avoid that by making a
"show" and a "get" function, rather than 2 different "get" functions.
Anyway, I realize that I'm novice enough that I'm quite likely trying
to justify a poor design decision. Any further thoughts on this?
It's open to some question, but it's not the question I was asking. A
hash _is_ a numeric value, so it might also be reasonable to just have a
function to get the value (probably as some user-defined long-integer
type) and then separately have functions to deal with formatting that
type for display, storage, etc. That's a bit beyond what I had in mind
at the moment though.
good point. I think I'll change it, since there is no reason to keep
the object once it has returned it's value, and the:
class instance(data);
instance.hash();
motif that needs to be used with the current setup is awkward. a
simple:
string hashfunction(data);
function would be less awkward to use.
I quite agree -- it looks (to me) like the only other time you use the
hash object after creation is the display function we discussed above.
It looks to me like you may have had something somewhat different in
mind to start with, but it ended up being simplified out of existence
before all was said and done.
One thing that might be worth considering is defining your own type to
hold the hash value -- it doesn't look to me like a string is the ideal
type for the job.
What's the better way? I was basically trying to avoid parsing the
filespec multiple times, or passing so many strings (eg path + root +
ext) into functions...seemed easier (and less error-pront) to pass the
class.
It depends -- as-is, you might about as well have a single function that
manipulates data in a normal struct. For a class to make much sense,
the class should encapsulate _something_. As-is, your class has almost
no intelligence, no encapsulation, etc.
Well...I was writing PRNG's with names that were descriptive (to me
anyway) of how they worked. Slicerclass happened to be a pretty good
one at generating solid random data that passes all tests for
randomness that I'm aware of. I decided to keep the PRNG as a
stand-alone class that spits out random data, rather than to write it
as an encrypter that accept files and spit out encrypted files.
(other than having a more useful name like My_PRNG) do you have a
suggestion about how to use the PRNG? Would you write a "super-class"
that includes all the functionality of a PRNG, and all the
functionality of the hasher, and all the functionality of the
encrypter, and the associated helper functions?
No -- rather the contrary. I'd probably split things up quite a bit
more finely. Right now, your random number generator has one function
that's really related to generating a random number, which is good, but
also has things to give direct access to the key (almost certainly NOT
good) getting an init vector and system size (apparently both of which
are somehow related to repeating a sequence, but only in some rather
ill-defined way.
I'd have a couple of classes. First would be an PRNG state. It would
incorporate enough to be able to store a state of the PRNG, and restore
it later -- rather than your get_system_size, get_init_vector, etc.,
being stored (and manipulated?) by the user in some unknown way, have a
PRNG state that can be created, stored, assigned, and used to create a
stream.
Separate from that, I'd have the encryptor that combines the random
stream with the data to produce the encrypted stream.
I thought that I had
essentially done this with my "driver" function, while keeping my PRNG
class (slicer_class) usable as a general purpose PRNG.
Perhaps I missed something, but right now the separation doesn't look
very clean, and your encryption seems to know quite a bit about the
internals of the PRNG, to the point that you probably could not (for one
example) plug in some totally different PRNG at a moment's notice.
Well, since I built authentication into the system, the user *needs*
to know if he correctly unencrypted the file. While I agree that
telling him that he got it correct would make a dictionary attack
easier (if I understand the attack that you imply), I thought it
wasn't really an issue since I wrote the prog so that such an attack
would be costly at circa 1+ second / try.
That would sort of apply in the case of a dictionary attack, but really
would not to a dictionary attack. A PRNG is basically an algorithmic
way of creating a large, but still finite, sequence of numbers. The
seed to the PRNG simply selects a point in that sequence at which to
start using numbers.
When you do your second of looping, you still end up selecting _some_
point in that sequence. If I skip over the second of looping, I pick
some point in the sequence as well. If I'm doing a brute-force attack,
my plan is to simply look at _every_ starting point in the sequence
until I find the one you used -- and the fact that I got there by a
somewhat different route than you did is utterly irrelevant.
IOW, a brute force attack has no reason whatsoever to use one second per
candidate key.
I haven't tried to figure out the details of a dictionary attack, but in
your bounce(), you seem to use only linear operations. Assuming that's
correct, any number of iterations can be collapsed down to a single,
constant-time operation, meaning your 1-second loop can be reduced to a
matter of a few nanoseconds.
Anyhow, this is getting wildly off-topic, so I'll leave it alone for
now.