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.
Contents |
[edit] 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;
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
#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
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
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'Second: Use 'openssl' from Ruby's standard library.
puts Digest::SHA1.hexdigest('Rosetta Code')
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
PackageLoader fileInPackage: 'Digest'.
(SHA1 hexDigestOf: 'Rosetta Code') displayNl.
(SHA1Stream hashValueOf:'Rosetta Code')
[edit] Tcl
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
$ echo -n 'ASCII string' | sha1
9e9aeefe5563845ec5c42c5630842048c0fc261b
$ echo -n 'ASCII string' | openssl sha1 | sed 's/.*= //'
9e9aeefe5563845ec5c42c5630842048c0fc261b