SHA-1

From Rosetta Code
Revision as of 12:58, 26 February 2012 by 98.234.249.218 (talk) (→‎{{header|OCaml}}: added perl)
Task
SHA-1
You are encouraged to solve this task according to the task description, using any language you may know.

SHA-1 or SHA1 is a one-way hash function; it computes a 160-bit message digest. SHA-1 often appears in security protocols; for example, many HTTPS websites use RSA with SHA-1 to secure their connections. BitTorrent uses SHA-1 to verify downloads. Git and Mercurial use SHA-1 digests to identify commits.

A US government standard, FIPS 180-1, defines SHA-1.

Find the SHA-1 message digest for a string of octets. You may either call a SHA-1 library, or implement SHA-1 in your language. Both approaches interest Rosetta Code.

Warning: SHA-1 has known weaknesses. Theoretical attacks may find a collision after 252 operations, or perhaps fewer. This is much faster than a brute force attack of 280 operations. US government deprecated SHA-1. For production-grade cryptography, users may consider a stronger alternative, such as SHA-256 (from the SHA-2 family) or the upcoming SHA-3.

Ada

Works with: GNAT

<lang Ada>with Ada.Text_IO; with GNAT.SHA1;

procedure Main is begin

  Ada.Text_IO.Put_Line ("SHA1 (""Rosetta Code"") = " &
                        GNAT.SHA1.Digest ("Rosetta Code"));

end Main;</lang>

Output:

SHA1 ("Rosetta Code") = 48c98f7e5a6e736d790ab740dfc3f51a61abe2b5

C#

Tests the built-in SHA1CryptoServiceProvider: <lang csharp>using System; using System.Security.Cryptography; using System.Text; using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace RosettaCode.SHA1 {

   [TestClass]
   public class SHA1CryptoServiceProviderTest
   {
       [TestMethod]
       public void TestComputeHash()
       {
           var input = new UTF8Encoding().GetBytes("Rosetta Code");
           var output = new SHA1CryptoServiceProvider().ComputeHash(input);
           Assert.AreEqual(
               "48-C9-8F-7E-5A-6E-73-6D-79-0A-B7-40-DF-C3-F5-1A-61-AB-E2-B5",
               BitConverter.ToString(output));
       }
   }

}</lang>

Clojure

As Clojure is interoperable with Java the solution to this task would be a small modification to MD5, as with Java. (Replacing "MD5" with "SHA-1" as noted here.)

Factor

Factor provides sha1 in the checksums.sha vocabulary. In Factor, checksum-bytes returns a sequence of bytes; hex-string converts this sequence to a hexadecimal string.

IN: scratchpad USING: checksums checksums.sha ;
IN: scratchpad "Rosetta Code" sha1 checksum-bytes hex-string .
"48c98f7e5a6e736d790ab740dfc3f51a61abe2b5"

The implementation is at basis/checksums/sha/sha.factor.

Go

<lang go>package main

import (

   "crypto/sha1"
   "fmt"

)

func main() {

   h := sha1.New()
   h.Write([]byte("Rosetta Code"))
   fmt.Printf("%x\n", h.Sum(nil))

}</lang> Output:

48c98f7e5a6e736d790ab740dfc3f51a61abe2b5

Java

The solution to this task would be a small modification to MD5 (replacing "MD5" with "SHA-1" as noted here).

Mathematica

<lang Mathematica>IntegerString[Hash["Rosetta Code", "SHA1"], 16]

-> 48c98f7e5a6e736d790ab740dfc3f51a61abe2b5</lang>

OCaml

Using the library ocaml-sha in the interactive loop:

<lang ocaml>$ ocaml -I +sha sha1.cma

       Objective Caml version 3.12.1
  1. Sha1.to_hex (Sha1.string "Rosetta Code") ;;

- : string = "48c98f7e5a6e736d790ab740dfc3f51a61abe2b5"</lang>

Perl

<lang perl>use Digest::SHA qw(sha1_hex);

print sha1_hex('Rosetta Code'), "\n";</lang>

The same in OO manner <lang perl>use Digest::SHA;

my $sha1 = Digest::SHA->new(1); $sha1->add('Rosetta Code'); print $sha1->hexdigest, "\n";</lang>

Python

<lang python>import hashlib h = hashlib.sha1() h.update(bytes("Ars longa, vita brevis", encoding="ASCII")) h.hexdigest()

  1. "e640d285242886eb96ab80cbf858389b3df52f43"</lang>

Ruby

These programs print the SHA-1 of 'Rosetta Code', which is 48c98f7e5a6e736d790ab740dfc3f51a61abe2b5.

First: Use 'digest' from Ruby's standard library. <lang ruby>require 'digest' puts Digest::SHA1.hexdigest('Rosetta Code')</lang>

Second: Use 'openssl' from Ruby's standard library.

Library: OpenSSL

<lang ruby>require 'openssl' puts OpenSSL::Digest::SHA1.hexdigest('Rosetta Code')</lang>

Third: Reimplement SHA-1 in Ruby. <lang ruby>require 'stringio'

  1. Calculates SHA-1 message digest of _string_. Returns digest as
  2. binary string.
  3. --
  4. This is a simple, pure-Ruby implementation of SHA-1, following
  5. the algorithm in FIPS 180-1.
  6. ++

def sha1(string)

 # functions and constants
 mask = (1 << 32) - 1
 s = proc{|n, x| ((x << n) & mask) | (x >> (32 - n))}
 f = [
   proc {|b, c, d| (b & c) | (b.^(mask) & d)},
   proc {|b, c, d| b ^ c ^ d},
   proc {|b, c, d| (b & c) | (b & d) | (c & d)},
   proc {|b, c, d| b ^ c ^ d},
 ].freeze
 k = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6].freeze
 # initial hash
 h = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0]
 io = StringIO.new(string)
 block = ""
 term = false  # appended "\x80" in second-last block?
 last = false  # last block?
 until last
   # Read next block of 16 words (64 bytes, 512 bits).
   io.read(64, block)
   # Unpack block into 32-bit words "N".
   case len = block.length
   when 64
     # Unpack 16 words.
     w = block.unpack("N16")
   when 56..63
     # Second-last block: append padding, unpack 16 words.
     block.concat("\x80"); term = true
     block.concat("\0" * (63 - len))
     w = block.unpack("N16")
   when 0..55
     # Last block: append padding, unpack 14 words.
     block.concat(term ? "\0" : "\x80")
     block.concat("\0" * (55 - len))
     w = block.unpack("N14")
     # Append bit length, 2 words.
     bit_len = string.length << 3
     w.push(bit_len >> 32, bit_len & mask)
     last = true
   else
     fail "impossible"
   end
   # Process block.
   (16..79).each {|t|
     w[t] = s[1, w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]]}
   a, b, c, d, e = h[0..4]
   t = 0
   (0..3).each {|i|
     20.times {
       temp = (s[5, a] + f[i][b, c, d] + e + w[t] + k[i]) & mask
       e = d; d = c; c = s[30, b]; b = a; a = temp
       t += 1}}
   h[0] = (h[0] + a) & mask
   h[1] = (h[1] + b) & mask
   h[2] = (h[2] + c) & mask
   h[3] = (h[3] + d) & mask
   h[4] = (h[4] + e) & mask
 end
 h.pack("N5")

end

  1. Hexadecimal-encode a binary _string_.

def hexencode(string)

 # We use String#each_byte for compatibility with Ruby 1.8.6.
 result = ""
 string.each_byte {|byte| result << ("%02x" % byte)}
 result

end

if __FILE__ == $0

 # Print some example SHA-1 digests.
 # FIPS 180-1 has correct digests for 'abc' and 'abc...opq'.
 [
   'abc',
   'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq',
   'Rosetta Code',
 ].each {|s|
   printf("%s:\n  %s\n", s, hexencode(sha1 s))
 }

end</lang>

Tcl

Library: Tcllib (Package: sha1)

<lang tcl>package require sha1 puts [sha1::sha1 "Rosetta Code"]</lang> Output:

48c98f7e5a6e736d790ab740dfc3f51a61abe2b5

It should be noted that the sha1 package is actually a façade that uses an efficient implementation in C if one is available, or a pure Tcl version otherwise.

UNIX Shell

Works with: OpenBSD version 2.2 (link)

<lang bash>$ echo -n 'ASCII string' | sha1 9e9aeefe5563845ec5c42c5630842048c0fc261b</lang>

Library: OpenSSL

<lang bash>$ echo -n 'ASCII string' | openssl sha1 | sed 's/.*= //' 9e9aeefe5563845ec5c42c5630842048c0fc261b</lang>