Continue working on the Ruby extension

This commit is contained in:
Hongli Lai (Phusion) 2012-10-04 18:30:56 +02:00
parent 0edf5aee7a
commit b97c745e6c
7 changed files with 717 additions and 3 deletions

View 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
View 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

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

View 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

View file

@ -1,2 +1,2 @@
require 'mkmf' require 'mkmf'
create_makefile('sha3') create_makefile('digest/sha3')

View file

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

View 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