SHA-1

From Rosetta Code
Jump to: navigation, search
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.

Contents

[edit] Ada

Works with: GNAT
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;

Output:

SHA1 ("Rosetta Code") = 48c98f7e5a6e736d790ab740dfc3f51a61abe2b5

[edit] BBC BASIC

[edit] Library

      PRINT FNsha1("Rosetta Code")
END
 
DEF FNsha1(message$)
LOCAL buflen%, buffer%, hprov%, hhash%, hash$, i%
CALG_SHA1 = &8004
CRYPT_VERIFYCONTEXT = &F0000000
HP_HASHVAL = 2
PROV_RSA_FULL = 1
buflen% = 64
DIM buffer% LOCAL buflen%-1
SYS "CryptAcquireContext", ^hprov%, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT
SYS "CryptCreateHash", hprov%, CALG_SHA1, 0, 0, ^hhash%
SYS "CryptHashData", hhash%, message$, LEN(message$), 0
SYS "CryptGetHashParam", hhash%, HP_HASHVAL, buffer%, ^buflen%, 0
SYS "CryptDestroyHash", hhash%
SYS "CryptReleaseContext", hprov%
FOR i% = 0 TO buflen%-1
hash$ += RIGHT$("0" + STR$~buffer%?i%, 2)
NEXT
= hash$

Output:

48C98F7E5A6E736D790AB740DFC3F51A61ABE2B5

[edit] Native

      *FLOAT64
PRINT FNsha1("Rosetta Code")
END
 
DEF FNsha1(message$)
LOCAL a%, b%, c%, d%, e%, f%, i%, j%, k%, l%, t%
LOCAL h0%, h1%, h2%, h3%, h4%, w%()
 
REM Initialize variables:
h0% = &67452301
h1% = &EFCDAB89
h2% = &98BADCFE
h3% = &10325476
h4% = &C3D2E1F0
 
l% = LEN(message$)*8
 
REM Pre-processing:
REM append the bit '1' to the message:
message$ += CHR$&80
 
REM append k bits '0', where k is the minimum number >= 0 such that
REM the resulting message length (in bits) is congruent to 448 (mod 512)
WHILE (LEN(message$) MOD 64) <> 56
message$ += CHR$0
ENDWHILE
 
REM append length of message (before pre-processing), in bits, as
REM 64-bit big-endian integer
FOR i% = 56 TO 0 STEP -8
message$ += CHR$(l% >>> i%)
NEXT
 
REM Process the message in successive 512-bit chunks:
REM break message into 512-bit chunks, for each chunk
REM break chunk into sixteen 32-bit big-endian words w[i], 0 <= i <= 15
 
DIM w%(79)
FOR j% = 0 TO LEN(message$) DIV 64 - 1
 
FOR i% = 0 TO 15
w%(i%) = !(!^message$ + 64*j% + 4*i%)
SWAP ?(^w%(i%)+0),?(^w%(i%)+3)
SWAP ?(^w%(i%)+1),?(^w%(i%)+2)
NEXT i%
 
REM Extend the sixteen 32-bit words into eighty 32-bit words:
FOR i% = 16 TO 79
w%(i%) = w%(i%-3) EOR w%(i%-8) EOR w%(i%-14) EOR w%(i%-16)
w%(i%) = (w%(i%) << 1) OR (w%(i%) >>> 31)
NEXT i%
 
REM Initialize hash value for this chunk:
a% = h0%
b% = h1%
c% = h2%
d% = h3%
e% = h4%
 
REM Main loop:
FOR i% = 0 TO 79
CASE TRUE OF
WHEN 0 <= i% AND i% <= 19
f% = (b% AND c%) OR ((NOT b%) AND d%)
k% = &5A827999
WHEN 20 <= i% AND i% <= 39
f% = b% EOR c% EOR d%
k% = &6ED9EBA1
WHEN 40 <= i% AND i% <= 59
f% = (b% AND c%) OR (b% AND d%) OR (c% AND d%)
k% = &8F1BBCDC
WHEN 60 <= i% AND i% <= 79
f% = b% EOR c% EOR d%
k% = &CA62C1D6
ENDCASE
 
t% = FN32(((a% << 5) OR (a% >>> 27)) + f% + e% + k% + w%(i%))
e% = d%
d% = c%
c% = (b% << 30) OR (b% >>> 2)
b% = a%
a% = t%
 
NEXT i%
 
REM Add this chunk's hash to result so far:
h0% = FN32(h0% + a%)
h1% = FN32(h1% + b%)
h2% = FN32(h2% + c%)
h3% = FN32(h3% + d%)
h4% = FN32(h4% + e%)
 
NEXT j%
 
= FNhex(h0%) + FNhex(h1%) + FNhex(h2%) + FNhex(h3%) + FNhex(h4%)
 
DEF FNhex(A%) = RIGHT$("0000000"+STR$~A%,8)
 
DEF FN32(n#)
WHILE n# > &7FFFFFFF : n# -= 2^32 : ENDWHILE
WHILE n# < &80000000 : n# += 2^32 : ENDWHILE
= n#

Output:

48C98F7E5A6E736D790AB740DFC3F51A61ABE2B5

[edit] C

Library: OpenSSL
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/sha.h>
 
int main()
{
int i;
unsigned char result[SHA_DIGEST_LENGTH];
const char *string = "Rosetta Code";
 
SHA1(string, strlen(string), result);
 
for(i = 0; i < SHA_DIGEST_LENGTH; i++)
printf("%02x%c", result[i], i < (SHA_DIGEST_LENGTH-1) ? ' ' : '\n');
 
return EXIT_SUCCESS;
}

[edit] C++

using the Poco crypto libraries, compiling with g++ -lPocoCrypto shaexample.cpp -o shaexample

#include <string>
#include <iostream>
#include "Poco/SHA1Engine.h"
#include "Poco/DigestStream.h"
 
using Poco::DigestEngine ;
using Poco::SHA1Engine ;
using Poco::DigestOutputStream ;
 
int main( ) {
std::string myphrase ( "Rosetta Code" ) ;
SHA1Engine sha1 ;
DigestOutputStream outstr( sha1 ) ;
outstr << myphrase ;
outstr.flush( ) ; //to pass everything to the digest engine
const DigestEngine::Digest& digest = sha1.digest( ) ;
std::cout << myphrase << " as a sha1 digest :" << DigestEngine::digestToHex( digest )
<< " !" << std::endl ;
return 0 ;
}

Output:

Rosetta Code as a sha1 digest :48c98f7e5a6e736d790ab740dfc3f51a61abe2b5 !

[edit] C#

Tests the built-in SHA1CryptoServiceProvider:

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));
}
}
}

[edit] Caché ObjectScript

USER>set hash=$System.Encryption.SHA1Hash("Rosetta Code")
USER>zzdump hash
0000: 48 C9 8F 7E 5A 6E 73 6D 79 0A B7 40 DF C3 F5 1A
0010: 61 AB E2 B5

[edit] 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.)

[edit] Common Lisp

Library: ironclad

This example uses the Ironclad cryptography library (available via Quicklisp as well).

;;; in addition to sha1, ironclad provides sha224, sha256, sha384, and sha512.
(defun sha1-hash (data)
(let ((sha1 (ironclad:make-digest 'ironclad:sha1))
(bin-data (ironclad:ascii-string-to-byte-array data)))
(ironclad:update-digest sha1 bin-data)
(ironclad:byte-array-to-hex-string (ironclad:produce-digest sha1))))
 

[edit] D

Translation of: Python
import std.stdio, std.digest.sha;
 
void main() {
writefln("%-(%02x%)", "Ars longa, vita brevis".sha1Of());
}
Output:
e640d285242886eb96ab80cbf858389b3df52f43

[edit] 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.

[edit] Go

package main
 
import (
"crypto/sha1"
"fmt"
)
 
func main() {
h := sha1.New()
h.Write([]byte("Rosetta Code"))
fmt.Printf("%x\n", h.Sum(nil))
}

Output:

48c98f7e5a6e736d790ab740dfc3f51a61abe2b5

[edit] Java

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

[edit] Mathematica

IntegerString[Hash["Rosetta Code", "SHA1"], 16]
 
-> 48c98f7e5a6e736d790ab740dfc3f51a61abe2b5

[edit] NetRexx

This solution is basically the same as that for MD5, substituting "SHA-1" for "MD5" as the algorithm to use in the MessageDigest instance.

/* NetRexx */
options replace format comments java crossref savelog symbols binary
 
import java.security.MessageDigest
 
SHA1('Rosetta Code', '48c98f7e5a6e736d790ab740dfc3f51a61abe2b5')
 
return
 
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method SHA1(messageText, verifyCheck) public static
 
algorithm = 'SHA-1'
digestSum = getDigest(messageText, algorithm)
 
say '<Message>'messageText'</Message>'
say Rexx('<'algorithm'>').right(12) || digestSum'</'algorithm'>'
say Rexx('<Verify>').right(12) || verifyCheck'</Verify>'
if digestSum == verifyCheck then say algorithm 'Confirmed'
else say algorithm 'Failed'
 
return
 
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method getDigest(messageText = Rexx, algorithm = Rexx 'MD5', encoding = Rexx 'UTF-8', lowercase = boolean 1) public static returns Rexx
 
algorithm = algorithm.upper
encoding = encoding.upper
 
message = String(messageText)
messageBytes = byte[]
digestBytes = byte[]
digestSum = Rexx ''
 
do
messageBytes = message.getBytes(encoding)
md = MessageDigest.getInstance(algorithm)
md.update(messageBytes)
digestBytes = md.digest
 
loop b_ = 0 to digestBytes.length - 1
bb = Rexx(digestBytes[b_]).d2x(2)
if lowercase then digestSum = digestSum || bb.lower
else digestSum = digestSum || bb.upper
end b_
catch ex = Exception
ex.printStackTrace
end
 
return digestSum
 

Output:

<Message>Rosetta Code</Message>
     <SHA-1>48c98f7e5a6e736d790ab740dfc3f51a61abe2b5</SHA-1>
    <Verify>48c98f7e5a6e736d790ab740dfc3f51a61abe2b5</Verify>
SHA-1 Confirmed

[edit] OCaml

Using the library ocaml-sha in the interactive loop:

$ ocaml -I +sha sha1.cma
Objective Caml version 3.12.1
 
# Sha1.to_hex (Sha1.string "Rosetta Code") ;;
- : string = "48c98f7e5a6e736d790ab740dfc3f51a61abe2b5"

[edit] Perl

use Digest::SHA qw(sha1_hex);
 
print sha1_hex('Rosetta Code'), "\n";
Output:
48c98f7e5a6e736d790ab740dfc3f51a61abe2b5

The same in OO manner

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


[edit] Perl 6

A pure Perl 6 implementation that closely follows the description of SHA-1 in FIPS 180-1. Slow.

sub postfix:<mod2³²>(\x) { x % 2**32 }
sub infix:<>(\x,\y) { (x + y)mod2³² }
sub S(\n,\X) { (X +< n)mod2³² +| (X +> (32-n)) }
 
my \f = -> \B,\C,\D { (B +& C) +| ((+^B)mod2³² +& D) },
-> \B,\C,\D { B +^ C +^ D },
-> \B,\C,\D { (B +& C) +| (B +& D) +| (C +& D) },
-> \B,\C,\D { B +^ C +^ D };
 
my \K = 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6;
 
sub sha1-pad(Buf $msg)
{
my \bits = 8 * $msg.elems;
my @padded = $msg.list, 0x80, 0x00 xx (-(bits div 8 + 1 + 8) % 64);
@padded.map({ :256[$^a,$^b,$^c,$^d] }), (bits +> 32)mod2³², (bits)mod2³²;
}
 
sub sha1-block(@H is rw, @M)
{
my @W = @M;
@W.push: S(1, @W[$_-3] +^ @W[$_-8] +^ @W[$_-14] +^ @W[$_-16]) for 16..79;
 
my ($A,$B,$C,$D,$E) = @H;
for 0..79 -> \t {
my \TEMP = S(5,$A) ⊕ f[t div 20]($B,$C,$D)$E@W[t] ⊕ K[t div 20];
$E = $D; $D = $C; $C = S(30,$B); $B = $A; $A = TEMP;
}
@H «⊕=» ($A,$B,$C,$D,$E);
}
 
sub sha1(Buf $msg)
{
my @M = sha1-pad($msg);
my @H = 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0;
sha1-block(@H,@M[$_..$_+15]) for 0,16...^+@M;
@H;
}
 
say sha1($_.encode('ascii'))».base(16), " $_"
for 'abc',
'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq',
'Rosetta Code',
'Ars longa, vita brevis';

Output:

A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D  abc
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1  abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq
48C98F7E 5A6E736D 790AB740 DFC3F51A 61ABE2B5  Rosetta Code
E640D285 242886EB 96AB80CB F858389B 3DF52F43  Ars longa, vita brevis

[edit] PHP

<?php
$string = 'Rosetta Code';
echo sha1( $string ), "\n";
?>
Output:
48c98f7e5a6e736d790ab740dfc3f51a61abe2b5

[edit] PicoLisp

(let Str "Rosetta Code"
(pack
(mapcar '((B) (pad 2 (hex B)))
(native "libcrypto.so" "SHA1" '(B . 20) Str (length Str) '(NIL (20))) ) ) )

Output:

-> "48C98F7E5A6E736D790AB740DFC3F51A61ABE2B5"

[edit] Python

import hashlib
h = hashlib.sha1()
h.update(bytes("Ars longa, vita brevis", encoding="ASCII"))
h.hexdigest()
# "e640d285242886eb96ab80cbf858389b3df52f43"

[edit] Racket

With the built-in file/sha1 library:

 
#lang racket
(require file/sha1)
(sha1 (open-input-string "Rosetta Code"))
 

With the faster openssl/sha1 library (requires OpenSSL to be installed):

 
#lang racket
(require openssl/sha1)
(sha1 (open-input-string "Rosetta Code"))
 

[edit] Ruby

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

First: Use 'digest' from Ruby's standard library.

require 'digest'
puts Digest::SHA1.hexdigest('Rosetta Code')
Second: Use 'openssl' from Ruby's standard library.
Library: OpenSSL
require 'openssl'
puts OpenSSL::Digest::SHA1.hexdigest('Rosetta Code')

Third: Reimplement SHA-1 in Ruby.

require 'stringio'
 
# Calculates SHA-1 message digest of _string_. Returns binary digest.
# For hexadecimal digest, use +*sha1(string).unpack('H*')+.
#--
# This is a simple, pure-Ruby implementation of SHA-1, following
# the algorithm in FIPS 180-1.
#++
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) or (
# Work around a bug in Rubinius 1.2.4. At eof,
# MRI and JRuby already replace block with "".
block.replace("")
)
 
# 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
 
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, *sha1(s).unpack('H*'))
}
end

[edit] Smalltalk

Works with: GNU Smalltalk
PackageLoader fileInPackage: 'Digest'.
(SHA1 hexDigestOf: 'Rosetta Code') displayNl.
Works with: Smalltalk/X
(SHA1Stream hashValueOf:'Rosetta Code')

[edit] Tcl

Library: Tcllib (Package: sha1)
package require sha1
puts [sha1::sha1 "Rosetta Code"]

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.

[edit] UNIX Shell

Works with: OpenBSD version 2.2 (link)
$ echo -n 'ASCII string' | sha1
9e9aeefe5563845ec5c42c5630842048c0fc261b
Library: OpenSSL
$ echo -n 'ASCII string' | openssl sha1 | sed 's/.*= //'
9e9aeefe5563845ec5c42c5630842048c0fc261b
Personal tools
Namespaces

Variants
Actions
Community
Explore
Misc
Toolbox