My apologies for the formatting; evidently my e-mail editor decided to "help 
out". Hopefully the message still scans despite that.

> From: [email protected]
> To: [email protected]
> Subject: RE: Crypto hierarchy is a *good thing*
> Date: Mon, 25 Oct 2010 13:52:25 -0600
> 
> Personally, I dislike String-based factory methods. To me, that feels like 
> old-think Java. I'd rather instantiate a specific type, with the type-safety 
> and self-documenting benefits that provides. It makes for less involuted 
> code, in my opinion. Faced with a decision between:
> Hash hasher = new Sha256Hash(object);
> and
> Hash hasher = SomeHashFactory.newHasher("SHA-256", object);
> and
> Hash hasher = new SomeMasterClassThatHasEveryAlgorithm("SHA-256", object);
> 
> I would choose to use the first every time, if it was available. That's the 
> reason JDOM was such a successful Java library for XML--it did away with all 
> the extraneous interfaces and String-based factory methods of the XML API 
> built into the JDK and gave developers exactly what they really wanted to 
> work with: a model of concrete, type-safe objects. The way Shiro's Hash 
> hierarchy is built is exactly what I as a user of the framework would want. 
> Additionally, the presence of toHex() and toBase64() on the interface and 
> implementation is also something I want, as a user. I have an intense dislike 
> for what I view as the standard Java approach of "Make the hard things easy 
> and the easy things obtuse." I don't want to have to write code like:
> Hash hash = new Sha512Hash(object);
> byte[] hashBytes = hash.getBytes();
> 
> Encoder encoder = new Base64Encoder();
> String base64Encoded = encoder.encode(hashBytes);
> 
> To me, that feels just like Java forcing me to do this to read a line from 
> System.in:
> BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
> br.readLine();
> versus
> Console.ReadLine();
> in C#.
> 
> As an end user of the framework, I don't want or need all the extra 
> indirection. As an end user, I don't want or need "perfect" architectural 
> design. What I want is a straightforward API that gives me access to the 
> functions I want at the point where I need them that also gives me the 
> ability to go lower-level if I choose to, or have a specific reason for doing 
> so. With the current Hash interface, I can immediately get a Base-64 encoded 
> version of my Hash without having to use another set of objects to get it. 
> But, if I want to use my own custom encoding technique, I can do that too 
> because I also have access to the raw hashed bytes.
> 
> There's certainly a limit to how much of this convenience you want to build 
> into APIs. It can lead to bloat, making it hard to find what you're looking 
> for in documentation and in code, and it can also lead to extensibility and 
> maintainability issues. However, if carefully thought out, it can also result 
> in a much more usable, friendly API. I'm not looking for a security framework 
> with textbook perfect architecture and the leanest, DRYest interfaces. I'm 
> looking for one that makes hard security operations easy (something Shiro 
> does well) while keeping the easy things easy too.
> 
> Additionally, with regards to the use of inheritance in Shiro, I would say 
> it’s very well-regulated. At this point I have ported roughly 1/3 to 1/2 of 
> shiro-core to C#, so I’m intimately familiar with how the internals interact. 
> While the inheritance hierarchy is deep, a deep hierarchy is not, in and of 
> itself, an indicator that there’s a problem. Shiro’s hierarchy was 
> intentionally constructed to separate concerns (which I think it does a good 
> job of) and to allow developers who need to have higher control over the 
> exact behavior of the framework to get it by allowing them to subclass and 
> take control of the hierarchy at any point. There may be some cleanup that’s 
> possible (I’ve found a few places in my work on porting Shiro to C# where I 
> think things could be tightened up a bit, certainly), but that’s to be 
> expected of any framework this old.>
> Best regards,> Bryan>
> > Date: Mon, 25 Oct 2010 12:08:49 -0700
> > Subject: Re: Crypto hierarchy is a *good thing*
> > From: [email protected]
> > To: [email protected]
> > 
> > Just to clarify, the 'crypto hierarchy' that Kalle and I were talking
> > about at the time was regarding the CipherService implementations, not
> > the Hash implementations.
> > 
> > > My response here is that we should have.
> > >
> > > try {
> > >  Hasher hasher = new MessageDigestHasher("SHA-512");
> > >
> > >  HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(hasher);
> > > } catch(NoSuchAlgorithmException nsae)
> > > {
> > > }
> > 
> > There is no reason for this IMO - this is essentially no different to
> > the end-user than using the MessageDigest class directly.  Shiro uses
> > unchecked exceptions for everything as a design tenet.  The end-user
> > has the choice to catch a CryptoException if they want to react to a
> > potentially erroneous algorithm name.
> > 
> > > Strings specification for algorithms are there for a reason, pluggable 
> > > algorithms into the JVM.  If it's known, a priori, that the algorithm is 
> > > in every JVM, e.g. SHA-512, then one can use a helper method.
> > 
> > They're there for a reason due to a procedurally-oriented JDK
> > implementation that foregos type-safety and interface-based design
> > goals (in a type-safe language!).  The CipherService and Hash
> > interfaces in Shiro exist to circumvent these design issues and to
> > provide end-users a checked-exception-free, type-safe and intuitive
> > API.
> > 
> > > Now, with that said.  Look at all the classes we can remove.   Quite a 
> > > lot.
> > 
> > We can remove the concrete Hash implementations, but I don't agree
> > that we should.   Without question, the number one design goal of
> > Shiro is ease-of-use, even if it means maintaining a little more code
> > by the dev team. A lot of people are using code like this:
> > 
> > new Sha1Hash(blah).toBase64()
> > new Md5Hash(foo).toHex()
> > 
> > which is a just a joy to use as an end-user and more readable compared
> > to anything the JDK provides.
> > 
> > So, even if we can remove the Hash implementations and ask everyone to
> > move to using SimpleHash("SHA-1", blah).toBase64() instead, I don't
> > know that we should.  The additional feature of type-safety (which
> > also eliminates erroneous input: "is it SHA1? or SHA-1?  or sha-1?")
> > can be used for reflection and other configuration mechanisms is a
> > _nice_ thing.  Keeping 6 or 7 or so Hash implementations that never
> > change for this level of convenience is a suitable concession to me.
> > And we retain backwards compatibility, which is ideal if we can do it,
> > even when moving to 2.0.
> > 
> > >> new Sha512Hash(aFile).toHex()
> > >>
> > >> is _much_ nicer for end users than using the JDK's crappy
> > >> MessageDigest class.  It is also type safe.  Using a string to
> > 
> > > What I have an issue with here is that you've also bundled in the 
> > > encoding.  That should be decoupled.
> > 
> > I agree with you on principle and try to do this almost always -
> > separate orthogonal concerns and not combine them.  However, in this
> > particular case, I think practicality wins out.  Shiro is not a
> > framework 'on a hill' that mandates perfect architectural design.  We
> > strive for it when possible, but when in conflict with practicality,
> > practicality should 'win out'.
> > 
> > When working with hashes and output from Ciphers, the need to
> > hex-encode or base64-encode the resulting data is so strong, they
> > should be immediately accessible for the end-user.  This is a
> > real-world use-case where I think architectural philosophy takes a
> > back seat.
> > 
> > Without the toBase64() and toHex() methods, now and end-user has to go
> > find out how to do this themselves.  They could search for a while in
> > Shiro's APIs or go read the documentation, or resort unnecessarily to
> > commons-codec because they didn't know they didn't have to - or they
> > could just use their IDE's auto-complete feature and have a working
> > solution in seconds.
> > 
> > The same philosophy exists in Java's Object class's toString() method.
> >  Surely creating a string representation of an object (XML? JSON?
> > Simple string name?) is architecturally orthogonal to the object's
> > reason for existence.  It is included (and forced upon) Java
> > developers - something not to be taken lightly in such a core language
> > feature - because it is used so darn often, that real-world use
> > justifies its inclusion.
> > 
> > I think this same principle applies to the ByteSource interface and
> > its implementations given their usage patterns in an application.
> > 
> > My .02,
> > 
> > Les
>                                         
                                          

Reply via email to