Skip to content

Instantly share code, notes, and snippets.

@JackVCurtis
Created February 20, 2015 18:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JackVCurtis/b516b5e57538773245da to your computer and use it in GitHub Desktop.
Save JackVCurtis/b516b5e57538773245da to your computer and use it in GitHub Desktop.
Single block implementation of SHA1 in Ruby. DO NOT USE THIS IN REAL LIFE.
def rot_left(num, count)
bin_string = num.to_s(2)
bin_string = ("0" * (32 - bin_string.length)) + bin_string
shifted_string = bin_string[0..(count-1)]
rotated_string = bin_string[count..31] + shifted_string
return rotated_string.to_i(2)
end
def lsb_32(num)
s = num.to_s(2)
s.length < 32 ? s = ("0" * (32 - s.length)) + s : s = s[-32, 32]
return s
end
h0 = "01100111010001010010001100000001".to_i(2)
h1 = "11101111110011011010101110001001".to_i(2)
h2 = "10011000101110101101110011111110".to_i(2)
h3 = "00010000001100100101010001110110".to_i(2)
h4 = "11000011110100101110000111110000".to_i(2)
puts "Enter value to hash:"
string = gets.chomp()
bin_array = string.split("").map do |c|
"0" * (8 - c.ord.to_s(2).length) + c.ord.to_s(2)
end
bin_string = bin_array.join("")
message = bin_string + "1"
until message.length % 512 == 448
message += "0"
end
padding = bin_string.length.to_s(2)
until padding.length == 64
padding = "0" + padding
end
message += padding
words = []
# Message padded to 512 bits
# puts message
16.times do |i|
words << message[i * 32, 32].to_i(2)
end
i = 16
until i == 80
w1 = words[i-3]
w2 = words[i-8]
w3 = words[i-14]
w4 = words[i-16]
new_word = w1 ^ w2 ^ w3 ^ w4
new_word = rot_left(new_word, 1)
words << new_word
i += 1
end
# generate 80 32-bit 'words' from the message
# puts words
a = h0
b = h1
c = h2
d = h3
e = h4
80.times do |i|
if i <= 19
neg_b = ~b
not_b = 31.downto(0).map {|n| neg_b[n]}.join.to_i(2)
f = (b & c) | (not_b & d)
k = "01011010100000100111100110011001".to_i(2)
elsif i > 19 && i <= 39
f = (b ^ c) ^ d
k = "01101110110110011110101110100001".to_i(2)
elsif i > 39 && i <= 59
f = ((b & c) | (b & d)) | (c & d)
k = "10001111000110111011110011011100".to_i(2)
elsif i > 59 && i <= 79
f = (b ^ c) ^ d
k = "11001010011000101100000111010110".to_i(2)
end
temp = rot_left(a, 5) + f + e + k + words[i]
temp = temp.to_s(2)[-32, 32].to_i(2)
e = d
d = c
c = rot_left(b, 30)
b = a
a = temp
end
h0 = lsb_32(h0 + a)
h1 = lsb_32(h1 + b)
h2 = lsb_32(h2 + c)
h3 = lsb_32(h3 + d)
h4 = lsb_32(h4 + e)
hash = h0.to_i(2).to_s(16) + h1.to_i(2).to_s(16) + h2.to_i(2).to_s(16) + h3.to_i(2).to_s(16) + h4.to_i(2).to_s(16)
puts hash
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment