Professional Documents
Culture Documents
#include "ripemd160_256.h"
// adapted by Pieter Wuille in 2012; all changes are in the public domain
// modified by Ryan Castellucci in 2015; all changes are in the public domain
/*
*
* RIPEMD160.c : RIPEMD-160 implementation
*
* Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
*
* ===================================================================
* The contents of this file are dedicated to the public domain. To
* the extent that dedication to the public domain is not available,
* everyone is granted a worldwide, perpetual, royalty-free,
* non-exclusive license to exercise all rights associated with the
* contents of this file for any purpose whatsoever.
* No rights are reserved.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
* ===================================================================
*
* Country of origin: Canada
*
* This implementation (written in C) is based on an implementation the author
* wrote in Python.
*
* This implementation was written with reference to the RIPEMD-160
* specification, which is available at:
* http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/
*
* It is also documented in the _Handbook of Applied Cryptography_, as
* Algorithm 9.55. It's on page 30 of the following PDF file:
* http://www.cacr.math.uwaterloo.ca/hac/about/chap9.pdf
*
* The RIPEMD-160 specification doesn't really tell us how to do padding, but
* since RIPEMD-160 is inspired by MD4, you can use the padding algorithm from
* RFC 1320.
*
* According to http://www.users.zetnet.co.uk/hopwood/crypto/scan/md.html:
* "RIPEMD-160 is big-bit-endian, little-byte-endian, and left-justified."
*/
#include <stdint.h>
#include <string.h>
#define RIPEMD160_DIGEST_SIZE 20
#define BLOCK_SIZE 64
/* cyclic left-shift the 32-bit word n left by s bits */
#define ROL(s, n) (((n) << (s)) | ((n) >> (32-(s))))
/* Ordering of message words. Based on the permutations rho(i) and pi(i), defined
as follows:
*
* rho(i) := { 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 }[i] 0 <= i
<= 15
*
* pi(i) := 9*i + 5 (mod 16)
*
* Line | Round 1 | Round 2 | Round 3 | Round 4 | Round 5
* -------+-----------+-----------+-----------+-----------+-----------
* left | id | rho | rho^2 | rho^3 | rho^4
* right | pi | rho pi | rho^2 pi | rho^3 pi | rho^4 pi
*/
/* Left line */
static const uint8_t RL[5][16] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, /* Round 1: id */
{ 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 }, /* Round 2: rho */
{ 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12 }, /* Round 3: rho^2
*/
{ 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2 }, /* Round 4: rho^3
*/
{ 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 } /* Round 5: rho^4
*/
};
/* Right line */
static const uint8_t RR[5][16] = {
{ 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12 }, /* Round 1: pi */
{ 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2 }, /* Round 2: rho pi
*/
{ 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13 }, /* Round 3: rho^2
pi */
{ 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14 }, /* Round 4: rho^3
pi */
{ 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 } /* Round 5: rho^4
pi */
};
/*
* Shifts - Since we don't actually re-order the message words according to
* the permutations above (we could, but it would be slower), these tables
* come with the permutations pre-applied.
*/
/* Boolean functions */
x.w = *v;
y.b[0] = x.b[3];
y.b[1] = x.b[2];
y.b[2] = x.b[1];
y.b[3] = x.b[0];
*v = y.w;
/* initialize state */
memcpy(h, initial_h, RIPEMD160_DIGEST_SIZE);
/* Load the left and right lines with the initial state */
AL = AR = h[0];
BL = BR = h[1];
CL = CR = h[2];
DL = DR = h[3];
EL = ER = h[4];
/* Round 1 */
round = 0;
for (w = 0; w < 16; w++) { /* left line */
T = ROL(SL[round][w], AL + F1(BL, CL, DL) + buf[RL[round][w]] + KL[round])
+ EL;
AL = EL; EL = DL; DL = ROL(10, CL); CL = BL; BL = T;
}
for (w = 0; w < 16; w++) { /* right line */
T = ROL(SR[round][w], AR + F5(BR, CR, DR) + buf[RR[round][w]] + KR[round])
+ ER;
AR = ER; ER = DR; DR = ROL(10, CR); CR = BR; BR = T;
}
/* Round 2 */
round++;
for (w = 0; w < 16; w++) { /* left line */
T = ROL(SL[round][w], AL + F2(BL, CL, DL) + buf[RL[round][w]] + KL[round])
+ EL;
AL = EL; EL = DL; DL = ROL(10, CL); CL = BL; BL = T;
}
for (w = 0; w < 16; w++) { /* right line */
T = ROL(SR[round][w], AR + F4(BR, CR, DR) + buf[RR[round][w]] + KR[round])
+ ER;
AR = ER; ER = DR; DR = ROL(10, CR); CR = BR; BR = T;
}
/* Round 3 */
round++;
for (w = 0; w < 16; w++) { /* left line */
T = ROL(SL[round][w], AL + F3(BL, CL, DL) + buf[RL[round][w]] + KL[round])
+ EL;
AL = EL; EL = DL; DL = ROL(10, CL); CL = BL; BL = T;
}
for (w = 0; w < 16; w++) { /* right line */
T = ROL(SR[round][w], AR + F3(BR, CR, DR) + buf[RR[round][w]] + KR[round])
+ ER;
AR = ER; ER = DR; DR = ROL(10, CR); CR = BR; BR = T;
}
/* Round 4 */
round++;
for (w = 0; w < 16; w++) { /* left line */
T = ROL(SL[round][w], AL + F4(BL, CL, DL) + buf[RL[round][w]] + KL[round])
+ EL;
AL = EL; EL = DL; DL = ROL(10, CL); CL = BL; BL = T;
}
for (w = 0; w < 16; w++) { /* right line */
T = ROL(SR[round][w], AR + F2(BR, CR, DR) + buf[RR[round][w]] + KR[round])
+ ER;
AR = ER; ER = DR; DR = ROL(10, CR); CR = BR; BR = T;
}
/* Round 5 */
round++;
for (w = 0; w < 16; w++) { /* left line */
T = ROL(SL[round][w], AL + F5(BL, CL, DL) + buf[RL[round][w]] + KL[round])
+ EL;
AL = EL; EL = DL; DL = ROL(10, CL); CL = BL; BL = T;
}
for (w = 0; w < 16; w++) { /* right line */
T = ROL(SR[round][w], AR + F1(BR, CR, DR) + buf[RR[round][w]] + KR[round])
+ ER;
AR = ER; ER = DR; DR = ROL(10, CR); CR = BR; BR = T;
}