On Oct 12, 1:38=A0pm, Jarsen <jason.lar... / gmail.com> wrote:
> On Oct 11, 11:56=A0pm, Josh Cheek <josh.ch... / gmail.com> wrote:
>
>
>
>
>
> > [Note: =A0parts of this message were removed to make it a legal post.]
>
> > On Mon, Oct 11, 2010 at 11:35 PM,JasonLarsen<jason.lar... / gmail.com>wro=
te:
>
> > > I'm trying to write a pure Ruby implementation of SHA1. In order to d=
o
> > > so, I need to be able to directly manipulate bits. I know about the
> > > bitwise operators in Ruby, but I'm having issues with the way that
> > > Ruby wraps things up in classes. Basically I've run into two problems=
.
>
> > > 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 byt=
e
> > > 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 bi=
t
> > > by bit if possible.
>
> > > I've seen the String.unpack and Array.pack used for binary data.
> > > However, I can only get the bits out in one glob str.unpack("B*"), or
> > > str.unpack("B8"*string.length), which still just gives me a bunch of
> > > stringified 8bit binary values. Seems like there should be a better
> > > way.
>
> > > 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?
>
> > > Any help would be greatly appreciated. Thanks in advance.
>
> > Hi, if you just need a portable SHA1 implementation, there is already o=
ne in
> > the standard library.http://ruby-doc.org/stdlib/libdoc/digest/rdoc/inde=
x.html
>
> > As for your problems, I'm finding myself really confused by your
> > terminology. For example, when you say "adding a one-bit and k zeros" d=
oes
> > that mean num + 2**k, Or is num <<=3D 1 ; num +=3D 1 ; num <<=3D k or s=
omething
> > else even?
>
> > It might be more helpful if you show "this is what I have, this is what=
 I
> > want, this is how I tried to get there"
>
> Sorry, looking back on that I even confused myself. I am aware of the
> SHA1 implementation in the standard library, I'm just trying to write
> one myself using pure Ruby.
>
> This is what I have so far for padding:
>
> def SHA1 message
> =A0 =A0 k =3D 448-((message.bitsize % block_bitsize) + 1)

      # EDIT
      # I think I need this here actually for certain cases
      k+=3D512 if k < 0

> =A0 =A0 m =3D message.unpack("B*")[0].to_i(2) << (k+65)
> =A0 =A0 padding =3D 1
> =A0 =A0 padding <<=3D k+64
> =A0 =A0 padding |=3D message.bitsize # then add last 64 bit block (messag=
e
> length) which is the len
> =A0 =A0 m |=3D padding # add the padding to the message
> =A0 =A0 #... split into 512-bit blocks
> =A0 =A0 #... do SHA1 operations
> end
>
> Where bitsize is defined as:
> =A0 =A0 class String; def bitsize; bytesize * 8; end; end
>
> The method so far seems to be giving me the correct value for m.
> However, my problem is with the leading zeros. For example, if the
> message is "abc, message.unpack("B*")[0] returns
> "011000010110001001100011". When I call to_i(2) on that number, the
> leading 0 bit will disappear - which makes sense because to 01 an 1
> are both the same number.
>
> However, when I begin to perform sha1 operations on those blocks I
> will need that leading 0 back; in the example where message =3D "abc",
> m.to_s(2) or will only give me a 511 digit long output, when I need a
> 512 bit block. So I need to figure out how to keep those leading zeros
> in place so I have the correct block size. Hopefully this makes more
> sense.