Jason Larsen wrote in post #949355: > PROBLEM 1: I need to pad the message by appending a 1-bit, and then a > certain number of 0s. When appending numbers (e.g. 0b1) to the end of > by string, Ruby wraps each number in its Fixnum class making it 1 byte > long: So basically adding 0b1 appends 0b0000_0001, which is 7 zeros > that shouldn't be there. The fix I've found is I to tack 0x80 on the > end, which concats 0b1000_0000. The downside is that I have to keep > track of my zeros in batches of bytes (which at this point my > implementation handles alright), but I'd like to know how to do it bit > by bit if possible. A String in ruby is a collection of bytes, not bits. I think you'll find that as long as your input to your sha1 algorithm is also a String, and thus a multiple of 8 bits, everything will work fine. The way the sha1 algorithm is defined it can be implemented for an input which is not a multiple of 8 bits, but as you've found, it's not easy to represent that anyway :-) Therefore, if you want your implementation to work with strange numbers of bits, you'll first need to choose an input representation. If I were you, I'd be happy to limit my implementation to inputs which are whole bytes. (After all, even a file on the filesystem is a whole number of bytes) > PROBLEM 2: After adding a one-bit and k zeros, I need to append a 64- > bit long integer representing the length of the message being hashed. > It seem like Fixnum is 8 bytes long on my machine, so the question is > how do I add a 64bit binary representation of this number to the end > of a string? Don't worry about Fixnum versus Bignum, that's internal to the implementation and mostly hidden. Even on a 32-bit machine you can make Integers which are 64-bits and above. Unfortunately, Array#pack("Q") works differently on little-endian and big-endian machines: irb(main):001:0> [255].pack("Q") => "\377\000\000\000\000\000\000\000" So for maximum portability I'd do two instances of "N", i.e. >> n = 0x0123456789abcdef => 81985529216486895 >> [n >> 32, n].pack("NN") => "\001#Eg\211\253\315\357" which you can check is correct like this: >> [n >> 32, n].pack("NN").unpack("H*") => ["0123456789abcdef"] Regards, Brian. -- Posted via http://www.ruby-forum.com/.