I feel I did well on functionality. The crack interface works well and with many different edge cases.
I implemented two modules here, dividing up different responsibilities between the two. I felt inheritance did not make sense for the way I tackled this project, as there is no state to pass down. It certainly would have been possible, but it would have felt wrong to implemenent.
I feel that I did well here, although possibly not as well as the previous items. My method for cracking is a little bit clunky, but everything works and is well named. I feel that the code is readable and is not overly long.
I feel again that I did well here. I am covering 100% of my code based on SimpleCov, as well all of my methods are tested. My only shortfall is that I did not use any mocks or stubs, which I felt were unnecessary as everthing is both unit and integration tested.
Lastly, I feel I did well here. I have 40 commits and 11 pull requests as of writing this, and they are all well named and communicate what I am doing. All items in pull requests are related, such as encrypt, decrypt, and crack.