Continue working on the Ruby extension
This commit is contained in:
parent
0edf5aee7a
commit
b97c745e6c
7 changed files with 717 additions and 3 deletions
300
ext/digest/KeccakF-1600-reference.c
Normal file
300
ext/digest/KeccakF-1600-reference.c
Normal file
|
@ -0,0 +1,300 @@
|
||||||
|
/*
|
||||||
|
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
|
||||||
|
Michaël Peeters and Gilles Van Assche. For more information, feedback or
|
||||||
|
questions, please refer to our website: http://keccak.noekeon.org/
|
||||||
|
|
||||||
|
Implementation by the designers,
|
||||||
|
hereby denoted as "the implementer".
|
||||||
|
|
||||||
|
To the extent possible under law, the implementer has waived all copyright
|
||||||
|
and related or neighboring rights to the source code in this file.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "brg_endian.h"
|
||||||
|
#include "displayIntermediateValues.h"
|
||||||
|
#include "KeccakNISTInterface.h"
|
||||||
|
#include "KeccakF-1600-interface.h"
|
||||||
|
|
||||||
|
typedef unsigned char UINT8;
|
||||||
|
typedef unsigned long long int UINT64;
|
||||||
|
|
||||||
|
#define nrRounds 24
|
||||||
|
UINT64 KeccakRoundConstants[nrRounds];
|
||||||
|
#define nrLanes 25
|
||||||
|
unsigned int KeccakRhoOffsets[nrLanes];
|
||||||
|
|
||||||
|
void KeccakPermutationOnWords(UINT64 *state);
|
||||||
|
void theta(UINT64 *A);
|
||||||
|
void rho(UINT64 *A);
|
||||||
|
void pi(UINT64 *A);
|
||||||
|
void chi(UINT64 *A);
|
||||||
|
void iota(UINT64 *A, unsigned int indexRound);
|
||||||
|
|
||||||
|
void fromBytesToWords(UINT64 *stateAsWords, const unsigned char *state)
|
||||||
|
{
|
||||||
|
unsigned int i, j;
|
||||||
|
|
||||||
|
for(i=0; i<(KeccakPermutationSize/64); i++) {
|
||||||
|
stateAsWords[i] = 0;
|
||||||
|
for(j=0; j<(64/8); j++)
|
||||||
|
stateAsWords[i] |= (UINT64)(state[i*(64/8)+j]) << (8*j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fromWordsToBytes(unsigned char *state, const UINT64 *stateAsWords)
|
||||||
|
{
|
||||||
|
unsigned int i, j;
|
||||||
|
|
||||||
|
for(i=0; i<(KeccakPermutationSize/64); i++)
|
||||||
|
for(j=0; j<(64/8); j++)
|
||||||
|
state[i*(64/8)+j] = (stateAsWords[i] >> (8*j)) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeccakPermutation(unsigned char *state)
|
||||||
|
{
|
||||||
|
#if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN)
|
||||||
|
UINT64 stateAsWords[KeccakPermutationSize/64];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
displayStateAsBytes(1, "Input of permutation", state);
|
||||||
|
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
|
||||||
|
KeccakPermutationOnWords((UINT64*)state);
|
||||||
|
#else
|
||||||
|
fromBytesToWords(stateAsWords, state);
|
||||||
|
KeccakPermutationOnWords(stateAsWords);
|
||||||
|
fromWordsToBytes(state, stateAsWords);
|
||||||
|
#endif
|
||||||
|
displayStateAsBytes(1, "State after permutation", state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeccakPermutationAfterXor(unsigned char *state, const unsigned char *data, unsigned int dataLengthInBytes)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for(i=0; i<dataLengthInBytes; i++)
|
||||||
|
state[i] ^= data[i];
|
||||||
|
KeccakPermutation(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeccakPermutationOnWords(UINT64 *state)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
displayStateAs64bitWords(3, "Same, with lanes as 64-bit words", state);
|
||||||
|
|
||||||
|
for(i=0; i<nrRounds; i++) {
|
||||||
|
displayRoundNumber(3, i);
|
||||||
|
|
||||||
|
theta(state);
|
||||||
|
displayStateAs64bitWords(3, "After theta", state);
|
||||||
|
|
||||||
|
rho(state);
|
||||||
|
displayStateAs64bitWords(3, "After rho", state);
|
||||||
|
|
||||||
|
pi(state);
|
||||||
|
displayStateAs64bitWords(3, "After pi", state);
|
||||||
|
|
||||||
|
chi(state);
|
||||||
|
displayStateAs64bitWords(3, "After chi", state);
|
||||||
|
|
||||||
|
iota(state, i);
|
||||||
|
displayStateAs64bitWords(3, "After iota", state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define index(x, y) (((x)%5)+5*((y)%5))
|
||||||
|
#define ROL64(a, offset) ((offset != 0) ? ((((UINT64)a) << offset) ^ (((UINT64)a) >> (64-offset))) : a)
|
||||||
|
|
||||||
|
void theta(UINT64 *A)
|
||||||
|
{
|
||||||
|
unsigned int x, y;
|
||||||
|
UINT64 C[5], D[5];
|
||||||
|
|
||||||
|
for(x=0; x<5; x++) {
|
||||||
|
C[x] = 0;
|
||||||
|
for(y=0; y<5; y++)
|
||||||
|
C[x] ^= A[index(x, y)];
|
||||||
|
}
|
||||||
|
for(x=0; x<5; x++)
|
||||||
|
D[x] = ROL64(C[(x+1)%5], 1) ^ C[(x+4)%5];
|
||||||
|
for(x=0; x<5; x++)
|
||||||
|
for(y=0; y<5; y++)
|
||||||
|
A[index(x, y)] ^= D[x];
|
||||||
|
}
|
||||||
|
|
||||||
|
void rho(UINT64 *A)
|
||||||
|
{
|
||||||
|
unsigned int x, y;
|
||||||
|
|
||||||
|
for(x=0; x<5; x++) for(y=0; y<5; y++)
|
||||||
|
A[index(x, y)] = ROL64(A[index(x, y)], KeccakRhoOffsets[index(x, y)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pi(UINT64 *A)
|
||||||
|
{
|
||||||
|
unsigned int x, y;
|
||||||
|
UINT64 tempA[25];
|
||||||
|
|
||||||
|
for(x=0; x<5; x++) for(y=0; y<5; y++)
|
||||||
|
tempA[index(x, y)] = A[index(x, y)];
|
||||||
|
for(x=0; x<5; x++) for(y=0; y<5; y++)
|
||||||
|
A[index(0*x+1*y, 2*x+3*y)] = tempA[index(x, y)];
|
||||||
|
}
|
||||||
|
|
||||||
|
void chi(UINT64 *A)
|
||||||
|
{
|
||||||
|
unsigned int x, y;
|
||||||
|
UINT64 C[5];
|
||||||
|
|
||||||
|
for(y=0; y<5; y++) {
|
||||||
|
for(x=0; x<5; x++)
|
||||||
|
C[x] = A[index(x, y)] ^ ((~A[index(x+1, y)]) & A[index(x+2, y)]);
|
||||||
|
for(x=0; x<5; x++)
|
||||||
|
A[index(x, y)] = C[x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void iota(UINT64 *A, unsigned int indexRound)
|
||||||
|
{
|
||||||
|
A[index(0, 0)] ^= KeccakRoundConstants[indexRound];
|
||||||
|
}
|
||||||
|
|
||||||
|
int LFSR86540(UINT8 *LFSR)
|
||||||
|
{
|
||||||
|
int result = ((*LFSR) & 0x01) != 0;
|
||||||
|
if (((*LFSR) & 0x80) != 0)
|
||||||
|
// Primitive polynomial over GF(2): x^8+x^6+x^5+x^4+1
|
||||||
|
(*LFSR) = ((*LFSR) << 1) ^ 0x71;
|
||||||
|
else
|
||||||
|
(*LFSR) <<= 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeccakInitializeRoundConstants()
|
||||||
|
{
|
||||||
|
UINT8 LFSRstate = 0x01;
|
||||||
|
unsigned int i, j, bitPosition;
|
||||||
|
|
||||||
|
for(i=0; i<nrRounds; i++) {
|
||||||
|
KeccakRoundConstants[i] = 0;
|
||||||
|
for(j=0; j<7; j++) {
|
||||||
|
bitPosition = (1<<j)-1; //2^j-1
|
||||||
|
if (LFSR86540(&LFSRstate))
|
||||||
|
KeccakRoundConstants[i] ^= (UINT64)1<<bitPosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeccakInitializeRhoOffsets()
|
||||||
|
{
|
||||||
|
unsigned int x, y, t, newX, newY;
|
||||||
|
|
||||||
|
KeccakRhoOffsets[index(0, 0)] = 0;
|
||||||
|
x = 1;
|
||||||
|
y = 0;
|
||||||
|
for(t=0; t<24; t++) {
|
||||||
|
KeccakRhoOffsets[index(x, y)] = ((t+1)*(t+2)/2) % 64;
|
||||||
|
newX = (0*x+1*y) % 5;
|
||||||
|
newY = (2*x+3*y) % 5;
|
||||||
|
x = newX;
|
||||||
|
y = newY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeccakInitialize()
|
||||||
|
{
|
||||||
|
KeccakInitializeRoundConstants();
|
||||||
|
KeccakInitializeRhoOffsets();
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayRoundConstants(FILE *f)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for(i=0; i<nrRounds; i++) {
|
||||||
|
fprintf(f, "RC[%02i][0][0] = ", i);
|
||||||
|
fprintf(f, "%08X", (unsigned int)(KeccakRoundConstants[i] >> 32));
|
||||||
|
fprintf(f, "%08X", (unsigned int)(KeccakRoundConstants[i] & 0xFFFFFFFFULL));
|
||||||
|
fprintf(f, "\n");
|
||||||
|
}
|
||||||
|
fprintf(f, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayRhoOffsets(FILE *f)
|
||||||
|
{
|
||||||
|
unsigned int x, y;
|
||||||
|
|
||||||
|
for(y=0; y<5; y++) for(x=0; x<5; x++) {
|
||||||
|
fprintf(f, "RhoOffset[%i][%i] = ", x, y);
|
||||||
|
fprintf(f, "%2i", KeccakRhoOffsets[index(x, y)]);
|
||||||
|
fprintf(f, "\n");
|
||||||
|
}
|
||||||
|
fprintf(f, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeccakInitializeState(unsigned char *state)
|
||||||
|
{
|
||||||
|
memset(state, 0, KeccakPermutationSizeInBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ProvideFast576
|
||||||
|
void KeccakAbsorb576bits(unsigned char *state, const unsigned char *data)
|
||||||
|
{
|
||||||
|
KeccakPermutationAfterXor(state, data, 72);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ProvideFast832
|
||||||
|
void KeccakAbsorb832bits(unsigned char *state, const unsigned char *data)
|
||||||
|
{
|
||||||
|
KeccakPermutationAfterXor(state, data, 104);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ProvideFast1024
|
||||||
|
void KeccakAbsorb1024bits(unsigned char *state, const unsigned char *data)
|
||||||
|
{
|
||||||
|
KeccakPermutationAfterXor(state, data, 128);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ProvideFast1088
|
||||||
|
void KeccakAbsorb1088bits(unsigned char *state, const unsigned char *data)
|
||||||
|
{
|
||||||
|
KeccakPermutationAfterXor(state, data, 136);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ProvideFast1152
|
||||||
|
void KeccakAbsorb1152bits(unsigned char *state, const unsigned char *data)
|
||||||
|
{
|
||||||
|
KeccakPermutationAfterXor(state, data, 144);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ProvideFast1344
|
||||||
|
void KeccakAbsorb1344bits(unsigned char *state, const unsigned char *data)
|
||||||
|
{
|
||||||
|
KeccakPermutationAfterXor(state, data, 168);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void KeccakAbsorb(unsigned char *state, const unsigned char *data, unsigned int laneCount)
|
||||||
|
{
|
||||||
|
KeccakPermutationAfterXor(state, data, laneCount*8);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ProvideFast1024
|
||||||
|
void KeccakExtract1024bits(const unsigned char *state, unsigned char *data)
|
||||||
|
{
|
||||||
|
memcpy(data, state, 128);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void KeccakExtract(const unsigned char *state, unsigned char *data, unsigned int laneCount)
|
||||||
|
{
|
||||||
|
memcpy(data, state, laneCount*8);
|
||||||
|
}
|
142
ext/digest/brg_endian.h
Normal file
142
ext/digest/brg_endian.h
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
|
||||||
|
|
||||||
|
LICENSE TERMS
|
||||||
|
|
||||||
|
The redistribution and use of this software (with or without changes)
|
||||||
|
is allowed without the payment of fees or royalties provided that:
|
||||||
|
|
||||||
|
1. source code distributions include the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer;
|
||||||
|
|
||||||
|
2. binary distributions include the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer in their documentation;
|
||||||
|
|
||||||
|
3. the name of the copyright holder is not used to endorse products
|
||||||
|
built using this software without specific written permission.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
|
||||||
|
This software is provided 'as is' with no explicit or implied warranties
|
||||||
|
in respect of its properties, including, but not limited to, correctness
|
||||||
|
and/or fitness for purpose.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Issue Date: 20/12/2007
|
||||||
|
Changes for ARM 9/9/2010
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BRG_ENDIAN_H
|
||||||
|
#define _BRG_ENDIAN_H
|
||||||
|
|
||||||
|
#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
|
||||||
|
#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* Include files where endian defines and byteswap functions may reside */
|
||||||
|
#if defined( __sun )
|
||||||
|
# include <sys/isa_defs.h>
|
||||||
|
#elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ )
|
||||||
|
# include <sys/endian.h>
|
||||||
|
#elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \
|
||||||
|
defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ )
|
||||||
|
# include <machine/endian.h>
|
||||||
|
#elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
|
||||||
|
# if !defined( __MINGW32__ ) && !defined( _AIX )
|
||||||
|
# include <endian.h>
|
||||||
|
# if !defined( __BEOS__ )
|
||||||
|
# include <byteswap.h>
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Now attempt to set the define for platform byte order using any */
|
||||||
|
/* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */
|
||||||
|
/* seem to encompass most endian symbol definitions */
|
||||||
|
|
||||||
|
#if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN )
|
||||||
|
# if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
|
||||||
|
# elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
|
||||||
|
# endif
|
||||||
|
#elif defined( BIG_ENDIAN )
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
|
||||||
|
#elif defined( LITTLE_ENDIAN )
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN )
|
||||||
|
# if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
|
||||||
|
# elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
|
||||||
|
# endif
|
||||||
|
#elif defined( _BIG_ENDIAN )
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
|
||||||
|
#elif defined( _LITTLE_ENDIAN )
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN )
|
||||||
|
# if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
|
||||||
|
# elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
|
||||||
|
# endif
|
||||||
|
#elif defined( __BIG_ENDIAN )
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
|
||||||
|
#elif defined( __LITTLE_ENDIAN )
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ )
|
||||||
|
# if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
|
||||||
|
# elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
|
||||||
|
# endif
|
||||||
|
#elif defined( __BIG_ENDIAN__ )
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
|
||||||
|
#elif defined( __LITTLE_ENDIAN__ )
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* if the platform byte order could not be determined, then try to */
|
||||||
|
/* set this define using common machine defines */
|
||||||
|
#if !defined(PLATFORM_BYTE_ORDER)
|
||||||
|
|
||||||
|
#if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \
|
||||||
|
defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \
|
||||||
|
defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \
|
||||||
|
defined( vax ) || defined( vms ) || defined( VMS ) || \
|
||||||
|
defined( __VMS ) || defined( _M_X64 )
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
|
||||||
|
|
||||||
|
#elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \
|
||||||
|
defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \
|
||||||
|
defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \
|
||||||
|
defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \
|
||||||
|
defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \
|
||||||
|
defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \
|
||||||
|
defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX )
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
|
||||||
|
|
||||||
|
#elif defined(__arm__)
|
||||||
|
# ifdef __BIG_ENDIAN
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
|
||||||
|
# else
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
|
||||||
|
# endif
|
||||||
|
#elif 1 /* **** EDIT HERE IF NECESSARY **** */
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
|
||||||
|
#elif 0 /* **** EDIT HERE IF NECESSARY **** */
|
||||||
|
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
|
||||||
|
#else
|
||||||
|
# error Please edit lines 132 or 134 in brg_endian.h to set the platform byte order
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
117
ext/digest/displayIntermediateValues.c
Normal file
117
ext/digest/displayIntermediateValues.c
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
|
||||||
|
Michaël Peeters and Gilles Van Assche. For more information, feedback or
|
||||||
|
questions, please refer to our website: http://keccak.noekeon.org/
|
||||||
|
|
||||||
|
Implementation by the designers,
|
||||||
|
hereby denoted as "the implementer".
|
||||||
|
|
||||||
|
To the extent possible under law, the implementer has waived all copyright
|
||||||
|
and related or neighboring rights to the source code in this file.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "displayIntermediateValues.h"
|
||||||
|
#include "KeccakNISTInterface.h"
|
||||||
|
|
||||||
|
FILE *intermediateValueFile = 0;
|
||||||
|
int displayLevel = 0;
|
||||||
|
|
||||||
|
void displaySetIntermediateValueFile(FILE *f)
|
||||||
|
{
|
||||||
|
intermediateValueFile = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void displaySetLevel(int level)
|
||||||
|
{
|
||||||
|
displayLevel = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayBytes(int level, const char *text, const unsigned char *bytes, unsigned int size)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if ((intermediateValueFile) && (level <= displayLevel)) {
|
||||||
|
fprintf(intermediateValueFile, "%s:\n", text);
|
||||||
|
for(i=0; i<size; i++)
|
||||||
|
fprintf(intermediateValueFile, "%02X ", bytes[i]);
|
||||||
|
fprintf(intermediateValueFile, "\n");
|
||||||
|
fprintf(intermediateValueFile, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayBits(int level, const char *text, const unsigned char *data, unsigned int size, int MSBfirst)
|
||||||
|
{
|
||||||
|
unsigned int i, iByte, iBit;
|
||||||
|
|
||||||
|
if ((intermediateValueFile) && (level <= displayLevel)) {
|
||||||
|
fprintf(intermediateValueFile, "%s:\n", text);
|
||||||
|
for(i=0; i<size; i++) {
|
||||||
|
iByte = i/8;
|
||||||
|
iBit = i%8;
|
||||||
|
if (MSBfirst)
|
||||||
|
fprintf(intermediateValueFile, "%d ", ((data[iByte] << iBit) & 0x80) != 0);
|
||||||
|
else
|
||||||
|
fprintf(intermediateValueFile, "%d ", ((data[iByte] >> iBit) & 0x01) != 0);
|
||||||
|
}
|
||||||
|
fprintf(intermediateValueFile, "\n");
|
||||||
|
fprintf(intermediateValueFile, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayStateAsBytes(int level, const char *text, const unsigned char *state)
|
||||||
|
{
|
||||||
|
displayBytes(level, text, state, KeccakPermutationSizeInBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayStateAs32bitWords(int level, const char *text, const unsigned int *state)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if ((intermediateValueFile) && (level <= displayLevel)) {
|
||||||
|
fprintf(intermediateValueFile, "%s:\n", text);
|
||||||
|
for(i=0; i<KeccakPermutationSize/64; i++) {
|
||||||
|
fprintf(intermediateValueFile, "%08X:%08X", (unsigned int)state[2*i+0], (unsigned int)state[2*i+1]);
|
||||||
|
if ((i%5) == 4)
|
||||||
|
fprintf(intermediateValueFile, "\n");
|
||||||
|
else
|
||||||
|
fprintf(intermediateValueFile, " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayStateAs64bitWords(int level, const char *text, const unsigned long long int *state)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if ((intermediateValueFile) && (level <= displayLevel)) {
|
||||||
|
fprintf(intermediateValueFile, "%s:\n", text);
|
||||||
|
for(i=0; i<KeccakPermutationSize/64; i++) {
|
||||||
|
fprintf(intermediateValueFile, "%08X", (unsigned int)(state[i] >> 32));
|
||||||
|
fprintf(intermediateValueFile, "%08X", (unsigned int)(state[i] & 0xFFFFFFFFULL));
|
||||||
|
if ((i%5) == 4)
|
||||||
|
fprintf(intermediateValueFile, "\n");
|
||||||
|
else
|
||||||
|
fprintf(intermediateValueFile, " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayRoundNumber(int level, unsigned int i)
|
||||||
|
{
|
||||||
|
if ((intermediateValueFile) && (level <= displayLevel)) {
|
||||||
|
fprintf(intermediateValueFile, "\n");
|
||||||
|
fprintf(intermediateValueFile, "--- Round %d ---\n", i);
|
||||||
|
fprintf(intermediateValueFile, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayText(int level, const char *text)
|
||||||
|
{
|
||||||
|
if ((intermediateValueFile) && (level <= displayLevel)) {
|
||||||
|
fprintf(intermediateValueFile, text);
|
||||||
|
fprintf(intermediateValueFile, "\n");
|
||||||
|
fprintf(intermediateValueFile, "\n");
|
||||||
|
}
|
||||||
|
}
|
29
ext/digest/displayIntermediateValues.h
Normal file
29
ext/digest/displayIntermediateValues.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
|
||||||
|
Michaël Peeters and Gilles Van Assche. For more information, feedback or
|
||||||
|
questions, please refer to our website: http://keccak.noekeon.org/
|
||||||
|
|
||||||
|
Implementation by the designers,
|
||||||
|
hereby denoted as "the implementer".
|
||||||
|
|
||||||
|
To the extent possible under law, the implementer has waived all copyright
|
||||||
|
and related or neighboring rights to the source code in this file.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _displayIntermediateValues_h_
|
||||||
|
#define _displayIntermediateValues_h_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void displaySetIntermediateValueFile(FILE *f);
|
||||||
|
void displaySetLevel(int level);
|
||||||
|
void displayBytes(int level, const char *text, const unsigned char *bytes, unsigned int size);
|
||||||
|
void displayBits(int level, const char *text, const unsigned char *data, unsigned int size, int MSBfirst);
|
||||||
|
void displayStateAsBytes(int level, const char *text, const unsigned char *state);
|
||||||
|
void displayStateAs32bitWords(int level, const char *text, const unsigned int *state);
|
||||||
|
void displayStateAs64bitWords(int level, const char *text, const unsigned long long int *state);
|
||||||
|
void displayRoundNumber(int level, unsigned int i);
|
||||||
|
void displayText(int level, const char *text);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,2 +1,2 @@
|
||||||
require 'mkmf'
|
require 'mkmf'
|
||||||
create_makefile('sha3')
|
create_makefile('digest/sha3')
|
||||||
|
|
|
@ -1,9 +1,126 @@
|
||||||
#include "ruby.h"
|
#include "ruby.h"
|
||||||
|
#include "KeccakNISTInterface.h"
|
||||||
|
|
||||||
static VALUE mDigest, mSHA3;
|
#define MAX_DIGEST_SIZE 64
|
||||||
|
|
||||||
|
static VALUE mDigest, cSHA3;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
hashState state;
|
||||||
|
int bitlen;
|
||||||
|
} RbSHA3;
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
rb_sha3_new(VALUE klass, VALUE bitlen) {
|
||||||
|
RbSHA3 *ctx;
|
||||||
|
VALUE obj;
|
||||||
|
|
||||||
|
ctx = (RbSHA3 *) xmalloc(sizeof(RbSHA3));
|
||||||
|
obj = Data_Wrap_Struct(klass, 0, xfree, ctx);
|
||||||
|
ctx->bitlen = NUM2INT(bitlen);
|
||||||
|
|
||||||
|
if (ctx->bitlen == 0) {
|
||||||
|
rb_raise(rb_eRuntimeError, "Unsupported hash length");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (Init(&ctx->state, ctx->bitlen)) {
|
||||||
|
case SUCCESS:
|
||||||
|
return obj;
|
||||||
|
case FAIL:
|
||||||
|
rb_raise(rb_eRuntimeError, "Unknown error");
|
||||||
|
return Qnil;
|
||||||
|
case BAD_HASHLEN:
|
||||||
|
rb_raise(rb_eRuntimeError, "Bad hash length (must be 0, 224, 256, 384 or 512)");
|
||||||
|
return Qnil;
|
||||||
|
default:
|
||||||
|
rb_raise(rb_eRuntimeError, "Unknown error code");
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
rb_sha3_copy(VALUE copy, VALUE obj) {
|
||||||
|
RbSHA3 *ctx_copy, *ctx_obj;
|
||||||
|
|
||||||
|
Data_Get_Struct(copy, RbSHA3, ctx_copy);
|
||||||
|
Data_Get_Struct(obj, RbSHA3, ctx_obj);
|
||||||
|
if (copy == obj) {
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
rb_check_frozen(copy);
|
||||||
|
|
||||||
|
memcpy(&ctx_copy->state, &ctx_obj->state, sizeof(hashState));
|
||||||
|
ctx_copy->bitlen = ctx_obj->bitlen;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
rb_sha3_reset(VALUE self) {
|
||||||
|
RbSHA3 *ctx;
|
||||||
|
|
||||||
|
Data_Get_Struct(self, RbSHA3, ctx);
|
||||||
|
Init(&ctx->state, ctx->bitlen);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
rb_sha3_update(VALUE self, VALUE str) {
|
||||||
|
RbSHA3 *ctx;
|
||||||
|
|
||||||
|
Data_Get_Struct(self, RbSHA3, ctx);
|
||||||
|
Update(&ctx->state, RSTRING_PTR(str), RSTRING_LEN(str) * 8);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
rb_sha3_digest(VALUE self, VALUE str) {
|
||||||
|
RbSHA3 *ctx;
|
||||||
|
hashState state;
|
||||||
|
unsigned char digest[MAX_DIGEST_SIZE];
|
||||||
|
|
||||||
|
Data_Get_Struct(self, RbSHA3, ctx);
|
||||||
|
memcpy(&state, &ctx->state, sizeof(hashState));
|
||||||
|
Final(&state, digest);
|
||||||
|
return rb_str_new((const char *) digest, ctx->bitlen / 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
rb_sha3_singleton_digest(int argc, VALUE *argv, VALUE klass) {
|
||||||
|
VALUE data, hashlen;
|
||||||
|
int i_hashlen;
|
||||||
|
unsigned char digest[MAX_DIGEST_SIZE];
|
||||||
|
|
||||||
|
if (rb_scan_args(argc, argv, "11", &data, &hashlen) == 1) {
|
||||||
|
i_hashlen = 512;
|
||||||
|
} else {
|
||||||
|
i_hashlen = NUM2INT(hashlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (Hash(i_hashlen, RSTRING_PTR(data), RSTRING_LEN(data) * 8, digest)) {
|
||||||
|
case SUCCESS:
|
||||||
|
return rb_str_new(digest, i_hashlen / 8);
|
||||||
|
case FAIL:
|
||||||
|
rb_raise(rb_eRuntimeError, "Unknown error");
|
||||||
|
return Qnil;
|
||||||
|
case BAD_HASHLEN:
|
||||||
|
rb_raise(rb_eRuntimeError, "Bad hash length (must be 0, 224, 256, 384 or 512)");
|
||||||
|
return Qnil;
|
||||||
|
default:
|
||||||
|
rb_raise(rb_eRuntimeError, "Unknown error code");
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Init_sha3() {
|
Init_sha3() {
|
||||||
mDigest = rb_define_module("Digest");
|
mDigest = rb_define_module("Digest");
|
||||||
mSHA3 = rb_define_module_under(mDigest, "SHA3");
|
cSHA3 = rb_define_class_under(mDigest, "SHA3", rb_cObject);
|
||||||
|
rb_define_singleton_method(cSHA3, "new", rb_sha3_new, 1);
|
||||||
|
rb_define_method(cSHA3, "initialize_copy", rb_sha3_copy, 1);
|
||||||
|
rb_define_method(cSHA3, "reset", rb_sha3_reset, 0);
|
||||||
|
rb_define_method(cSHA3, "update", rb_sha3_update, 1);
|
||||||
|
rb_define_method(cSHA3, "<<", rb_sha3_update, 1);
|
||||||
|
rb_define_method(cSHA3, "digest", rb_sha3_digest, 0);
|
||||||
|
rb_define_singleton_method(cSHA3, "digest", rb_sha3_singleton_digest, -1);
|
||||||
|
rb_require("digest/sha3/helpers");
|
||||||
}
|
}
|
||||||
|
|
9
lib/digest/sha3/helpers.rb
Normal file
9
lib/digest/sha3/helpers.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
Digest::SHA3.class_eval do
|
||||||
|
def self.hexdigest(*args)
|
||||||
|
digest(*args).unpack("H*").first
|
||||||
|
end
|
||||||
|
|
||||||
|
def hexdigest
|
||||||
|
digest.unpack("H*").first
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue