RIPEMD-160: Difference between revisions

11,047 bytes added ,  3 months ago
m
(→‎{{header|Raku}}: FP style (should also be faster))
m (→‎{{header|Wren}}: Minor tidy)
(12 intermediate revisions by 3 users not shown)
Line 185:
{{out}}
<pre>b3be159860842cebaa7174c8fff0aa9e50a5199f</pre>
 
=={{header|C++}}==
<syntaxhighlight lang="c++">
#include <bit>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
 
class RIPEMD160 {
public:
std::string message_digest(const std::string& message) {
std::vector<int64_t> state = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 };
 
std::vector<uint8_t> bytes = add_padding(message);
for ( uint64_t i = 0; i < bytes.size() / BLOCK_LENGTH; ++i ) {
std::vector<uint32_t> schedule(16, 0);
for ( uint32_t j = 0; j < BLOCK_LENGTH; ++j ) {
schedule[j / 4] |= ( bytes[i + j] ) << ( j % 4 * 8 );
}
 
int32_t a = state[0], b = state[1], c = state[2], d = state[3], e = state[4];
int32_t aa = state[0], bb = state[1], cc = state[2], dd = state[3], ee = state[4];
int32_t t = 0, tt = 0;
 
for ( uint32_t j = 0; j < 80; ++j ) {
uint32_t jj = j / 16;
t = std::rotl(a + ff(jj + 1, b, c, d) + schedule[RL[j]] + KL[jj], SL[j]) + e;
tt = std::rotl(aa + ff(5 - jj, bb, cc, dd) + schedule[RR[j]] + KR[jj], SR[j]) + ee;
 
a = e; e = d; d = std::rotl(static_cast<uint32_t>(c), 10); c = b; b = t;
aa = ee; ee = dd; dd = std::rotl(static_cast<uint32_t>(cc), 10); cc = bb; bb = tt;
}
 
t = state[1] + c + dd;
state[1] = state[2] + d + ee;
state[2] = state[3] + e + aa;
state[3] = state[4] + a + bb;
state[4] = state[0] + b + cc;
state[0] = t;
}
 
std::stringstream stream;
for ( uint32_t i = 0; i < state.size() * 4; ++i ) {
int8_t byte_value = static_cast<int8_t>(unsigned_right_shift(state[i / 4], i % 4 * 8));
stream << std::setfill('0') << std::setw(2) << std::hex << ( byte_value & 0xff );
}
return stream.str();
}
 
private:
std::vector<uint8_t> add_padding(const std::string& message) {
std::vector<uint8_t> bytes(message.begin(), message.end());
bytes.emplace_back(static_cast<uint8_t>(0x80));
 
uint32_t padding = BLOCK_LENGTH - ( bytes.size() % BLOCK_LENGTH );
if ( padding < 8 ) {
padding += BLOCK_LENGTH;
}
bytes.resize(bytes.size() + padding - 8, static_cast<uint8_t>(0x0));
 
const uint64_t bit_length = 8 * message.length();
for ( uint32_t i = 0; i < 8; ++i ) {
bytes.emplace_back(static_cast<uint8_t>( bit_length >> ( 8 * i ) ));
}
return bytes;
}
 
uint32_t ff(const uint32_t& group, const uint32_t& x, const uint32_t& y, const uint32_t& z) {
uint32_t result;
switch ( group ) {
case 1: result = x ^ y ^ z; break;
case 2: result = ( x & y ) | ( ~x & z ); break;
case 3: result = ( x | ~y ) ^ z; break;
case 4: result = ( x & z ) | ( y & ~z ); break;
case 5: result = x ^ ( y | ~z ); break;
default: throw std::invalid_argument("Unexpected argument: " + group);
};
return result;
}
 
int32_t unsigned_right_shift(const int32_t& base, const int32_t& shift) {
if ( shift < 0 || shift >= 32 ) {
throw std::invalid_argument("Shift must be in range 0..31: " + shift);
}
if ( base == 0 ) {
return 0;
}
return ( base > 0 ) ? base >> shift : static_cast<uint32_t>(base) >> shift;
}
 
const std::vector<uint32_t> SR = { 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 };
 
const std::vector<uint32_t> SL = { 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 };
 
const std::vector<uint32_t> RR = { 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 };
 
const std::vector<uint32_t> RL = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 };
 
const std::vector<uint32_t> KL = { 0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e };
const std::vector<uint32_t> KR = { 0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000 };
 
const uint32_t BLOCK_LENGTH = 64;
};
 
int main() {
RIPEMD160 ripemd160;
std::cout << ripemd160.message_digest("Rosetta Code") << std::endl;
}
</syntaxhighlight>
{{ out }}
<pre>
b3be159860842cebaa7174c8fff0aa9e50a5199f
</pre>
 
=={{header|Clojure}}==
Line 262 ⟶ 395:
b3be159860842cebaa7174c8fff0aa9e50a5199f
</pre>
 
=={{header|Fortran}}==
{{works with|Fortran|2003}}
 
<syntaxhighlight lang="fortran">program main
use, intrinsic :: iso_c_binding
implicit none
 
integer, parameter :: DIGEST_LEN = 20
integer, parameter :: HASH_LEN = 40
 
interface
function c_ripemd160(d, n, md) bind(c, name='RIPEMD160')
import :: c_char, c_long, c_ptr
implicit none
character(kind=c_char), intent(in) :: d
integer(kind=c_long), intent(in), value :: n
character(kind=c_char), intent(in) :: md
type(c_ptr) :: c_ripemd160
end function c_ripemd160
end interface
 
print '(a)', ripemd160('Rosetta Code')
contains
function ripemd160(str) result(hash)
character(len=*), intent(in) :: str
character(len=HASH_LEN) :: hash
 
character(len=DIGEST_LEN) :: raw
integer :: i
type(c_ptr) :: ptr
 
hash = ' '
ptr = c_ripemd160(str, len(str, kind=c_long), raw)
if (.not. c_associated(ptr)) return
write (hash, '(20z2.2)') (raw(i:i), i = 1, DIGEST_LEN)
end function ripemd160
end program main</syntaxhighlight>
 
{{out}}
<pre>B3BE159860842CEBAA7174C8FFF0AA9E50A5199F</pre>
 
=={{header|FreeBASIC}}==
Line 502 ⟶ 676:
}</syntaxhighlight>
{{out}}
<pre>
b3be159860842cebaa7174c8fff0aa9e50a5199f
</pre>
 
===Without external libraries===
<syntaxhighlight lang="java">
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
 
public final class RIPEMD160Task {
 
public static void main(String[] aArgs) {
System.out.println(RIPEMD160.messageDigest("Rosetta Code"));
}
 
}
 
final class RIPEMD160 {
public static String messageDigest(String aMessage) {
int[] state = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 };
byte[] bytes = addPadding(aMessage);
for ( int i = 0; i < bytes.length / BLOCK_LENGTH; i++ ) {
int[] schedule = new int[16];
for ( int j = 0; j < BLOCK_LENGTH; j++ ) {
schedule[j / 4] |= ( bytes[i * BLOCK_LENGTH + j] & 0xff ) << ( j % 4 * 8 );
}
int a = state[0], b = state[1], c = state[2], d = state[3], e = state[4];
int aa = state[0], bb = state[1], cc = state[2], dd = state[3], ee = state[4];
int t = 0, tt = 0;
for ( int j = 0; j < 80; j++ ) {
int jj = j / 16;
t = Integer.rotateLeft(a + ff(jj + 1, b, c, d) + schedule[RL[j]] + KL[jj], SL[j]) + e;
tt = Integer.rotateLeft(aa + ff(5 - jj, bb, cc, dd) + schedule[RR[j]] + KR[jj], SR[j]) + ee;
a = e; e = d; d = Integer.rotateLeft(c, 10); c = b; b = t;
aa = ee; ee = dd; dd = Integer.rotateLeft(cc, 10); cc = bb; bb = tt;
}
t = state[1] + c + dd;
state[1] = state[2] + d + ee;
state[2] = state[3] + e + aa;
state[3] = state[4] + a + bb;
state[4] = state[0] + b + cc;
state[0] = t;
}
String result = "";
for ( int i = 0; i < state.length * 4; i++ ) {
result += String.format("%02x", (byte) ( state[i / 4] >>> ( i % 4 * 8 ) ));
}
return result;
}
private static byte[] addPadding(String aMessage) {
byte[] bytes = aMessage.getBytes(StandardCharsets.UTF_8);
bytes = Arrays.copyOf(bytes, bytes.length + 1);
bytes[bytes.length - 1] = (byte) 0x80;
int padding = BLOCK_LENGTH - ( bytes.length % BLOCK_LENGTH );
if ( padding < 8 ) {
padding += BLOCK_LENGTH;
}
bytes = Arrays.copyOf(bytes, bytes.length + padding);
final long bitLength = aMessage.length() * 8;
for ( int i = 0; i < 8; i++ ) {
bytes[bytes.length - 8 + i] = (byte) ( bitLength >>> ( 8 * i ) );
}
return bytes;
}
private static int ff(int aGroup, int aX, int aY, int aZ) {
return switch ( aGroup ) {
case 1 -> aX ^ aY ^ aZ;
case 2 -> ( aX & aY ) | ( ~aX & aZ );
case 3 -> ( aX | ~aY ) ^ aZ;
case 4 -> ( aX & aZ ) | ( aY & ~aZ );
case 5 -> aX ^ ( aY | ~aZ );
default -> throw new IllegalArgumentException("Unexpected argument: " + aGroup);
};
}
private static final int[] KL = new int[] { 0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e };
private static final int[] KR = new int [] { 0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000 };
private static final int[] RL = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 };
private static final int[] RR = new int[] { 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 };
private static final int[] SL = new int[] { 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 };
private static final int[] SR = new int[] { 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 };
private static final int BLOCK_LENGTH = 64;
}
</syntaxhighlight>
{{ out }}
<pre>
b3be159860842cebaa7174c8fff0aa9e50a5199f
Line 1,248 ⟶ 1,540:
=end CREDITS
 
proto rmd160($) returns Blob is export {*}
multi rmd160(Str $str) { samewith $str.encode }
sub rotl(uint32 $n, $b) { $n +< $b +| $n +> (32 - $b) }
constant \r1 = <
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 7 4 13 1 10 6 15 3 12 0 9 5 2
14 11 8 3 10 14 4 9 15 8 1 2 7 0 6 13 11 5 12 1 9 11 10 0 8 12 4 13
3 7 15 14 5 6 2 4 0 5 9 7 12 2 10 14 1 3 8 11 6 15 13
>;
constant \r2 = <
5 14 7 0 9 2 11 4 13 6 15 8 1 10 3 12 6 11 3 7 0 13 5 10 14 15 8 12
4 9 1 2 15 5 1 3 7 14 6 9 11 8 12 2 10 0 4 13 8 6 4 1 3 11 15 0 5
12 2 13 9 7 10 14 12 15 10 4 1 5 8 7 6 2 13 14 0 3 9 11
>;
constant \s1 = <
11 14 15 12 5 8 7 9 11 13 14 15 6 7 9 8 7 6 8 13 11 9 7 15 7 12 15 9
11 7 13 12 11 13 6 7 14 9 13 15 14 8 13 6 5 12 7 5 11 12 14 15 14 15
9 8 9 14 5 6 8 6 5 12 9 15 5 11 6 8 13 12 5 12 13 14 11 8 5 6
>;
constant \s2 = <
8 9 9 11 13 15 15 5 7 7 8 11 14 14 12 6 9 13 15 7 12 8 9 11 7 7 12 7
6 15 13 11 9 7 15 11 8 6 6 14 12 13 5 14 13 13 7 5 15 5 8 11 14 14 6
14 6 9 12 9 12 5 15 8 8 5 12 9 12 5 14 6 8 13 6 5 15 13 11 11
>;
 
multi rmd160(Blob $data) {
constant @K1 = flat (0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e) »xx» 16;
constant @K2 = flat (0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000) »xx» 16;
 
sub rotl(uint32 $n, $b) { $n +< $b +| $n +> (32 - $b) }
my @F =
* +^ * +^ *,
{ $^x +& $^y +| +^$x +& $^z },
(* +| +^*) +^ *,
{ $^x +& $^z +| $^y +& +^$^z },
{ $^x +^ ($^y +| +^$^z) }
;
 
blob8.new:
my buf8 $b .= new: |@$data, 0x80;
map |*.polymod(256 xx 3),
$b.push: 0 until (8*@$b-448) %% 512;
|reduce
$b.push: |(8 * $data).polymod: 256 xx 7;
-> blob32 $h, @words {
blob32.new: [Z+] map {$_[[^5].rotate(++$)]}, $h, |await
blob8.new: (
map -> [&f, $r, @K, $s] {
reduce
start {
-> blob32 $h, @words {
reduce -> $A, $j {
my blob32 ($X, $Y) = reduce
-> [$X, $YA[4], $j {
rotl(
blob32.new($X[4], rotl(($X[0] + @F[ $j div 16](|$X[1..3]) + @words[r1[$j]] + @K1[$j]) mod 2**32, s1[$j]) + $X[4], $X[1], rotl($X[2], 10), $X[3]),
($A[0] + (BEGIN [
blob32.new($Y[4], rotl(($Y[0] + @F[(79-$j) div 16](|$Y[1..3]) + @words[r2[$j]] + @K2[$j]) mod 2**32, s2[$j]) + $Y[4], $Y[1], rotl($Y[2], 10), $Y[3]);
* +^ * +^ *,
}, blob32.new($h).clone xx 2, |^80;
{ $^x +& $^y +| +^$x +& $^z },
blob32.new: $h[1,2,3,4,0] Z+ $X[2,3,4,0,1] Z+ $Y[3,4,0,1,2];
(* +| +^*) +^ *,
},
{ $^x +& $^z +| $^y +& +^$^z },
(BEGIN blob32.new(0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0)),
{ $^x +^ ($^y +| +^$^z) }
|blob32.new($b.rotor(4).map: { :256[@^x.reverse] }).rotor(16);
])[&f($j) div 16](|$A[1..3])
).map: |*.polymod(256 xx 3);
+ @words[$r[$j]] + @K[$j]) mod 2**32,
$s[$j]
) + $A[4],
$A[1],
rotl($A[2], 10),
$A[3]
}, $h, |^80
}
},
BEGIN Array.new:
map -> [ &a,$b,@c,$d ] {
[&a,.($b),(flat @c »xx» 16),.($d)] given *.comb».parse-base(16)
},
( +*,
"0123456789ABCDEF74D1A6F3C0952EB83AE49F812706DB5C19BA08C4D37FE56240597C2AE138B6FD",
<0x00000000 0x5a827999 0x6ed9eba1 0x8f1bbcdc 0xa953fd4e>,
"BEFC5879BDEF6798768DB97F7CF9B7DCBD67E9DFE8D65C75BCEFEF989E56865C9F5B68DC5CDEB856"
),
(79-*,
"5E7092B4D6F81A3C6B370D5AEF8C4912F5137E69B8C2A04D86413BF05C2D97AECFA4158762DE039B",
<0x50a28be6 0x5c4dd124 0x6d703ef3 0x7a6d76e9 0x00000000>,
"899BDFF5778BEEC69DF7C89B77C76FDB97FB866ECD5EDD75F58BEE6E69C9C5F885C9C5E68D65FDBB"
)
;
},
(BEGIN blob32.new: 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0),
|blob32.new(
blob8.new(
$data.list,
0x80,
0 xx (-($data.elems + 1 + 8) % 64),
|(8 * $data).polymod: 256 xx 7
).rotor(4).map: { :256[@^x.reverse] }
).rotor(16);
}</syntaxhighlight>
 
Line 1,996 ⟶ 2,291:
{{libheader|Wren-crypto}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="ecmascriptwren">import "./crypto" for Ripemd160
import "./fmt" for Fmt
var strings = [
9,482

edits