├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── digest-sha3.gemspec ├── ext └── digest │ ├── KeccakF-1600-int-set.h │ ├── KeccakF-1600-interface.h │ ├── KeccakF-1600-reference.c │ ├── KeccakNISTInterface.c │ ├── KeccakNISTInterface.h │ ├── KeccakSponge.c │ ├── KeccakSponge.h │ ├── brg_endian.h │ ├── displayIntermediateValues.c │ ├── displayIntermediateValues.h │ ├── extconf.rb │ └── sha3.c ├── lib └── digest │ └── sha3 │ └── version.rb └── test ├── data ├── LongMsgKAT_224.txt ├── README ├── ShortMsgKAT_224.txt ├── ShortMsgKAT_256.txt ├── ShortMsgKAT_384.txt └── ShortMsgKAT_512.txt ├── generate_tests.rb ├── test_all.rb └── test_usage.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | *.o 3 | *.bundle 4 | Makefile 5 | test/test_vectors.rb 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2015 Phusion B.V. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | 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. 8 | 9 | This package contains code written by the Keccak authors, which is licensed http://creativecommons.org/publicdomain/zero/1.0/ -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .phony: all clean test 2 | 3 | all: ext/digest/Makefile 4 | make -C ext/digest 5 | 6 | ext/digest/Makefile: ext/digest/extconf.rb 7 | cd ext/digest && ruby extconf.rb 8 | 9 | clean: 10 | if [ -f ext/digest/Makefile ]; then make -C ext/digest clean; fi 11 | rm -f ext/digest/Makefile 12 | rm -f test/test_vectors.rb 13 | 14 | test: all test/test_vectors.rb 15 | ruby test/test_all.rb 16 | 17 | test/test_vectors.rb: test/generate_tests.rb test/data/* 18 | ruby test/generate_tests.rb > test/test_vectors.rb 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The SHA-3 (Keccak) extension for Ruby 2 | 3 | This Ruby extension implements the SHA-3 ([Keccak](http://keccak.noekeon.org/)) cryptographic hashing algorithm. It is based on the reference C implementation, version 3.2. The exposed interface is almost identical to that of the `digest` standard library. 4 | 5 | [](http://www.phusion.nl/) 6 | 7 | ## Installation 8 | 9 | gem install digest-sha3 10 | 11 | **Note**: as of version 1.1.0, digest-sha3 requires Ruby 2.2. The last version that worked on older versions was 1.0.2. 12 | 13 | ## Usage 14 | 15 | Keccak supports 5 hash lengths: 224-bit, 256-bit, 384-bit, 512-bit and variable length. Variable length is not supported by this Ruby extension. Unless the user specifies otherwise, this Ruby extension assumes 512-bit. 16 | 17 | require 'digest/sha3' 18 | 19 | # Generate 512-bit digest. 20 | Digest::SHA3.digest("foo") # => "\025\227\204*..." 21 | Digest::SHA3.hexdigest("foo") # => "1597842a..." 22 | 23 | # Generate 224-bit digest. 24 | Digest::SHA3.digest("foo", 224) # => "\332\251M\247..." 25 | Digest::SHA3.hexdigest("foo", 224) # => "daa94da7..." 26 | 27 | # Use this interface to feed data in chunks. 512-bit by default. 28 | digest = Digest::SHA3.new 29 | digest.update("f") 30 | digest.update("o") 31 | digest.update("o") 32 | digest.digest # => "\025\227\204*..." 33 | digest.hexdigest # => "1597842a..." 34 | 35 | # You can pass a hash length to the constructor. 36 | digest = Digest::SHA3.new(224) 37 | 38 | ## Running the test suite 39 | 40 | Run the test suite as follows: 41 | 42 | make test 43 | 44 | A part of the test suite is automatically generated from Keccak's reference test suite. 45 | 46 | ## Warning 47 | 48 | Do not use SHA-3 for hashing passwords. Do not even use SHA-3 + salt for hashing passowords. Use a [slow hash](http://codahale.com/how-to-safely-store-a-password/) instead. 49 | 50 | ## See also 51 | 52 | [node-sha3](https://github.com/phusion/node-sha3) 53 | -------------------------------------------------------------------------------- /digest-sha3.gemspec: -------------------------------------------------------------------------------- 1 | require File.expand_path('lib/digest/sha3/version') 2 | 3 | Gem::Specification.new do |s| 4 | s.name = "digest-sha3" 5 | s.version = Digest::SHA3::Version::STRING 6 | s.summary = "The SHA-3 (Keccak) hash" 7 | s.email = "software-signing@phusion.nl" 8 | s.homepage = "https://github.com/phusion/digest-sha3-ruby" 9 | s.description = "The SHA-3 (Keccak) hash." 10 | s.authors = ["Hongli Lai (Phusion)", "Keccak authors"] 11 | s.extensions << "ext/digest/extconf.rb" 12 | s.required_ruby_version = "~> 2.2" 13 | s.license = "MIT" 14 | 15 | s.files = Dir[ 16 | "README.md", 17 | "LICENSE", 18 | "Makefile", 19 | "digest-sha3.gemspec", 20 | "ext/**/*.{c,h,rb}", 21 | "lib/**/*" 22 | ] 23 | end 24 | -------------------------------------------------------------------------------- /ext/digest/KeccakF-1600-int-set.h: -------------------------------------------------------------------------------- 1 | #define ProvideFast576 2 | #define ProvideFast832 3 | #define ProvideFast1024 4 | #define ProvideFast1088 5 | #define ProvideFast1152 6 | #define ProvideFast1344 7 | -------------------------------------------------------------------------------- /ext/digest/KeccakF-1600-interface.h: -------------------------------------------------------------------------------- 1 | /* 2 | The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, 3 | Michaël Peeters and Gilles Van Assche. For more information, feedback or 4 | questions, please refer to our website: http://keccak.noekeon.org/ 5 | 6 | Implementation by the designers, 7 | hereby denoted as "the implementer". 8 | 9 | To the extent possible under law, the implementer has waived all copyright 10 | and related or neighboring rights to the source code in this file. 11 | http://creativecommons.org/publicdomain/zero/1.0/ 12 | */ 13 | 14 | #ifndef _KeccakPermutationInterface_h_ 15 | #define _KeccakPermutationInterface_h_ 16 | 17 | #include "KeccakF-1600-int-set.h" 18 | 19 | void KeccakInitialize( void ); 20 | void KeccakInitializeState(unsigned char *state); 21 | void KeccakPermutation(unsigned char *state); 22 | #ifdef ProvideFast576 23 | void KeccakAbsorb576bits(unsigned char *state, const unsigned char *data); 24 | #endif 25 | #ifdef ProvideFast832 26 | void KeccakAbsorb832bits(unsigned char *state, const unsigned char *data); 27 | #endif 28 | #ifdef ProvideFast1024 29 | void KeccakAbsorb1024bits(unsigned char *state, const unsigned char *data); 30 | #endif 31 | #ifdef ProvideFast1088 32 | void KeccakAbsorb1088bits(unsigned char *state, const unsigned char *data); 33 | #endif 34 | #ifdef ProvideFast1152 35 | void KeccakAbsorb1152bits(unsigned char *state, const unsigned char *data); 36 | #endif 37 | #ifdef ProvideFast1344 38 | void KeccakAbsorb1344bits(unsigned char *state, const unsigned char *data); 39 | #endif 40 | void KeccakAbsorb(unsigned char *state, const unsigned char *data, unsigned int laneCount); 41 | #ifdef ProvideFast1024 42 | void KeccakExtract1024bits(const unsigned char *state, unsigned char *data); 43 | #endif 44 | void KeccakExtract(const unsigned char *state, unsigned char *data, unsigned int laneCount); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /ext/digest/KeccakF-1600-reference.c: -------------------------------------------------------------------------------- 1 | /* 2 | The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, 3 | Michaël Peeters and Gilles Van Assche. For more information, feedback or 4 | questions, please refer to our website: http://keccak.noekeon.org/ 5 | 6 | Implementation by the designers, 7 | hereby denoted as "the implementer". 8 | 9 | To the extent possible under law, the implementer has waived all copyright 10 | and related or neighboring rights to the source code in this file. 11 | http://creativecommons.org/publicdomain/zero/1.0/ 12 | */ 13 | 14 | #include 15 | #include 16 | #include "brg_endian.h" 17 | #include "displayIntermediateValues.h" 18 | #include "KeccakNISTInterface.h" 19 | #include "KeccakF-1600-interface.h" 20 | 21 | typedef unsigned char UINT8; 22 | typedef unsigned long long int UINT64; 23 | 24 | #define nrRounds 24 25 | UINT64 KeccakRoundConstants[nrRounds]; 26 | #define nrLanes 25 27 | unsigned int KeccakRhoOffsets[nrLanes]; 28 | 29 | void KeccakPermutationOnWords(UINT64 *state); 30 | void theta(UINT64 *A); 31 | void rho(UINT64 *A); 32 | void pi(UINT64 *A); 33 | void chi(UINT64 *A); 34 | void iota(UINT64 *A, unsigned int indexRound); 35 | 36 | void fromBytesToWords(UINT64 *stateAsWords, const unsigned char *state) 37 | { 38 | unsigned int i, j; 39 | 40 | for(i=0; i<(KeccakPermutationSize/64); i++) { 41 | stateAsWords[i] = 0; 42 | for(j=0; j<(64/8); j++) 43 | stateAsWords[i] |= (UINT64)(state[i*(64/8)+j]) << (8*j); 44 | } 45 | } 46 | 47 | void fromWordsToBytes(unsigned char *state, const UINT64 *stateAsWords) 48 | { 49 | unsigned int i, j; 50 | 51 | for(i=0; i<(KeccakPermutationSize/64); i++) 52 | for(j=0; j<(64/8); j++) 53 | state[i*(64/8)+j] = (stateAsWords[i] >> (8*j)) & 0xFF; 54 | } 55 | 56 | void KeccakPermutation(unsigned char *state) 57 | { 58 | #if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN) 59 | UINT64 stateAsWords[KeccakPermutationSize/64]; 60 | #endif 61 | 62 | displayStateAsBytes(1, "Input of permutation", state); 63 | #if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) 64 | KeccakPermutationOnWords((UINT64*)state); 65 | #else 66 | fromBytesToWords(stateAsWords, state); 67 | KeccakPermutationOnWords(stateAsWords); 68 | fromWordsToBytes(state, stateAsWords); 69 | #endif 70 | displayStateAsBytes(1, "State after permutation", state); 71 | } 72 | 73 | void KeccakPermutationAfterXor(unsigned char *state, const unsigned char *data, unsigned int dataLengthInBytes) 74 | { 75 | unsigned int i; 76 | 77 | for(i=0; i> (64-offset))) : a) 110 | 111 | void theta(UINT64 *A) 112 | { 113 | unsigned int x, y; 114 | UINT64 C[5], D[5]; 115 | 116 | for(x=0; x<5; x++) { 117 | C[x] = 0; 118 | for(y=0; y<5; y++) 119 | C[x] ^= A[index(x, y)]; 120 | } 121 | for(x=0; x<5; x++) 122 | D[x] = ROL64(C[(x+1)%5], 1) ^ C[(x+4)%5]; 123 | for(x=0; x<5; x++) 124 | for(y=0; y<5; y++) 125 | A[index(x, y)] ^= D[x]; 126 | } 127 | 128 | void rho(UINT64 *A) 129 | { 130 | unsigned int x, y; 131 | 132 | for(x=0; x<5; x++) for(y=0; y<5; y++) 133 | A[index(x, y)] = ROL64(A[index(x, y)], KeccakRhoOffsets[index(x, y)]); 134 | } 135 | 136 | void pi(UINT64 *A) 137 | { 138 | unsigned int x, y; 139 | UINT64 tempA[25]; 140 | 141 | for(x=0; x<5; x++) for(y=0; y<5; y++) 142 | tempA[index(x, y)] = A[index(x, y)]; 143 | for(x=0; x<5; x++) for(y=0; y<5; y++) 144 | A[index(0*x+1*y, 2*x+3*y)] = tempA[index(x, y)]; 145 | } 146 | 147 | void chi(UINT64 *A) 148 | { 149 | unsigned int x, y; 150 | UINT64 C[5]; 151 | 152 | for(y=0; y<5; y++) { 153 | for(x=0; x<5; x++) 154 | C[x] = A[index(x, y)] ^ ((~A[index(x+1, y)]) & A[index(x+2, y)]); 155 | for(x=0; x<5; x++) 156 | A[index(x, y)] = C[x]; 157 | } 158 | } 159 | 160 | void iota(UINT64 *A, unsigned int indexRound) 161 | { 162 | A[index(0, 0)] ^= KeccakRoundConstants[indexRound]; 163 | } 164 | 165 | int LFSR86540(UINT8 *LFSR) 166 | { 167 | int result = ((*LFSR) & 0x01) != 0; 168 | if (((*LFSR) & 0x80) != 0) 169 | // Primitive polynomial over GF(2): x^8+x^6+x^5+x^4+1 170 | (*LFSR) = ((*LFSR) << 1) ^ 0x71; 171 | else 172 | (*LFSR) <<= 1; 173 | return result; 174 | } 175 | 176 | void KeccakInitializeRoundConstants() 177 | { 178 | UINT8 LFSRstate = 0x01; 179 | unsigned int i, j, bitPosition; 180 | 181 | for(i=0; i> 32)); 220 | fprintf(f, "%08X", (unsigned int)(KeccakRoundConstants[i] & 0xFFFFFFFFULL)); 221 | fprintf(f, "\n"); 222 | } 223 | fprintf(f, "\n"); 224 | } 225 | 226 | void displayRhoOffsets(FILE *f) 227 | { 228 | unsigned int x, y; 229 | 230 | for(y=0; y<5; y++) for(x=0; x<5; x++) { 231 | fprintf(f, "RhoOffset[%i][%i] = ", x, y); 232 | fprintf(f, "%2i", KeccakRhoOffsets[index(x, y)]); 233 | fprintf(f, "\n"); 234 | } 235 | fprintf(f, "\n"); 236 | } 237 | 238 | void KeccakInitializeState(unsigned char *state) 239 | { 240 | memset(state, 0, KeccakPermutationSizeInBytes); 241 | } 242 | 243 | #ifdef ProvideFast576 244 | void KeccakAbsorb576bits(unsigned char *state, const unsigned char *data) 245 | { 246 | KeccakPermutationAfterXor(state, data, 72); 247 | } 248 | #endif 249 | 250 | #ifdef ProvideFast832 251 | void KeccakAbsorb832bits(unsigned char *state, const unsigned char *data) 252 | { 253 | KeccakPermutationAfterXor(state, data, 104); 254 | } 255 | #endif 256 | 257 | #ifdef ProvideFast1024 258 | void KeccakAbsorb1024bits(unsigned char *state, const unsigned char *data) 259 | { 260 | KeccakPermutationAfterXor(state, data, 128); 261 | } 262 | #endif 263 | 264 | #ifdef ProvideFast1088 265 | void KeccakAbsorb1088bits(unsigned char *state, const unsigned char *data) 266 | { 267 | KeccakPermutationAfterXor(state, data, 136); 268 | } 269 | #endif 270 | 271 | #ifdef ProvideFast1152 272 | void KeccakAbsorb1152bits(unsigned char *state, const unsigned char *data) 273 | { 274 | KeccakPermutationAfterXor(state, data, 144); 275 | } 276 | #endif 277 | 278 | #ifdef ProvideFast1344 279 | void KeccakAbsorb1344bits(unsigned char *state, const unsigned char *data) 280 | { 281 | KeccakPermutationAfterXor(state, data, 168); 282 | } 283 | #endif 284 | 285 | void KeccakAbsorb(unsigned char *state, const unsigned char *data, unsigned int laneCount) 286 | { 287 | KeccakPermutationAfterXor(state, data, laneCount*8); 288 | } 289 | 290 | #ifdef ProvideFast1024 291 | void KeccakExtract1024bits(const unsigned char *state, unsigned char *data) 292 | { 293 | memcpy(data, state, 128); 294 | } 295 | #endif 296 | 297 | void KeccakExtract(const unsigned char *state, unsigned char *data, unsigned int laneCount) 298 | { 299 | memcpy(data, state, laneCount*8); 300 | } 301 | -------------------------------------------------------------------------------- /ext/digest/KeccakNISTInterface.c: -------------------------------------------------------------------------------- 1 | /* 2 | The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, 3 | Michaël Peeters and Gilles Van Assche. For more information, feedback or 4 | questions, please refer to our website: http://keccak.noekeon.org/ 5 | 6 | Implementation by the designers, 7 | hereby denoted as "the implementer". 8 | 9 | To the extent possible under law, the implementer has waived all copyright 10 | and related or neighboring rights to the source code in this file. 11 | http://creativecommons.org/publicdomain/zero/1.0/ 12 | */ 13 | 14 | #include 15 | #include "KeccakNISTInterface.h" 16 | #include "KeccakF-1600-interface.h" 17 | 18 | HashReturn Init(hashState *state, int hashbitlen) 19 | { 20 | switch(hashbitlen) { 21 | case 0: // Default parameters, arbitrary length output 22 | InitSponge((spongeState*)state, 1024, 576); 23 | break; 24 | case 224: 25 | InitSponge((spongeState*)state, 1152, 448); 26 | break; 27 | case 256: 28 | InitSponge((spongeState*)state, 1088, 512); 29 | break; 30 | case 384: 31 | InitSponge((spongeState*)state, 832, 768); 32 | break; 33 | case 512: 34 | InitSponge((spongeState*)state, 576, 1024); 35 | break; 36 | default: 37 | return BAD_HASHLEN; 38 | } 39 | state->fixedOutputLength = hashbitlen; 40 | return SUCCESS; 41 | } 42 | 43 | HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen) 44 | { 45 | if ((databitlen % 8) == 0) 46 | return Absorb((spongeState*)state, data, databitlen); 47 | else { 48 | HashReturn ret = Absorb((spongeState*)state, data, databitlen - (databitlen % 8)); 49 | if (ret == SUCCESS) { 50 | unsigned char lastByte; 51 | // Align the last partial byte to the least significant bits 52 | lastByte = data[databitlen/8] >> (8 - (databitlen % 8)); 53 | return Absorb((spongeState*)state, &lastByte, databitlen % 8); 54 | } 55 | else 56 | return ret; 57 | } 58 | } 59 | 60 | HashReturn Final(hashState *state, BitSequence *hashval) 61 | { 62 | return Squeeze(state, hashval, state->fixedOutputLength); 63 | } 64 | 65 | HashReturn Hash(int hashbitlen, const BitSequence *data, DataLength databitlen, BitSequence *hashval) 66 | { 67 | hashState state; 68 | HashReturn result; 69 | 70 | if ((hashbitlen != 224) && (hashbitlen != 256) && (hashbitlen != 384) && (hashbitlen != 512)) 71 | return BAD_HASHLEN; // Only the four fixed output lengths available through this API 72 | result = Init(&state, hashbitlen); 73 | if (result != SUCCESS) 74 | return result; 75 | result = Update(&state, data, databitlen); 76 | if (result != SUCCESS) 77 | return result; 78 | result = Final(&state, hashval); 79 | return result; 80 | } 81 | 82 | -------------------------------------------------------------------------------- /ext/digest/KeccakNISTInterface.h: -------------------------------------------------------------------------------- 1 | /* 2 | The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, 3 | Michaël Peeters and Gilles Van Assche. For more information, feedback or 4 | questions, please refer to our website: http://keccak.noekeon.org/ 5 | 6 | Implementation by the designers, 7 | hereby denoted as "the implementer". 8 | 9 | To the extent possible under law, the implementer has waived all copyright 10 | and related or neighboring rights to the source code in this file. 11 | http://creativecommons.org/publicdomain/zero/1.0/ 12 | */ 13 | 14 | #ifndef _KeccakNISTInterface_h_ 15 | #define _KeccakNISTInterface_h_ 16 | 17 | #include "KeccakSponge.h" 18 | 19 | typedef unsigned char BitSequence; 20 | typedef unsigned long long DataLength; 21 | typedef enum { SUCCESS = 0, FAIL = 1, BAD_HASHLEN = 2 } HashReturn; 22 | 23 | typedef spongeState hashState; 24 | 25 | /** 26 | * Function to initialize the state of the Keccak[r, c] sponge function. 27 | * The rate r and capacity c values are determined from @a hashbitlen. 28 | * @param state Pointer to the state of the sponge function to be initialized. 29 | * @param hashbitlen The desired number of output bits, 30 | * or 0 for Keccak[] with default parameters 31 | * and arbitrarily-long output. 32 | * @pre The value of hashbitlen must be one of 0, 224, 256, 384 and 512. 33 | * @return SUCCESS if successful, BAD_HASHLEN if the value of hashbitlen is incorrect. 34 | */ 35 | HashReturn Init(hashState *state, int hashbitlen); 36 | /** 37 | * Function to give input data for the sponge function to absorb. 38 | * @param state Pointer to the state of the sponge function initialized by Init(). 39 | * @param data Pointer to the input data. 40 | * When @a databitLen is not a multiple of 8, the last bits of data must be 41 | * in the most significant bits of the last byte. 42 | * @param databitLen The number of input bits provided in the input data. 43 | * @pre In the previous call to Absorb(), databitLen was a multiple of 8. 44 | * @return SUCCESS if successful, FAIL otherwise. 45 | */ 46 | HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen); 47 | /** 48 | * Function to squeeze output data from the sponge function. 49 | * If @a hashbitlen was not 0 in the call to Init(), the number of output bits is equal to @a hashbitlen. 50 | * If @a hashbitlen was 0 in the call to Init(), the output bits must be extracted using the Squeeze() function. 51 | * @param state Pointer to the state of the sponge function initialized by Init(). 52 | * @param hashval Pointer to the buffer where to store the output data. 53 | * @return SUCCESS if successful, FAIL otherwise. 54 | */ 55 | HashReturn Final(hashState *state, BitSequence *hashval); 56 | /** 57 | * Function to compute a hash using the Keccak[r, c] sponge function. 58 | * The rate r and capacity c values are determined from @a hashbitlen. 59 | * @param hashbitlen The desired number of output bits. 60 | * @param data Pointer to the input data. 61 | * When @a databitLen is not a multiple of 8, the last bits of data must be 62 | * in the most significant bits of the last byte. 63 | * @param databitLen The number of input bits provided in the input data. 64 | * @param hashval Pointer to the buffer where to store the output data. 65 | * @pre The value of hashbitlen must be one of 224, 256, 384 and 512. 66 | * @return SUCCESS if successful, BAD_HASHLEN if the value of hashbitlen is incorrect. 67 | */ 68 | HashReturn Hash(int hashbitlen, const BitSequence *data, DataLength databitlen, BitSequence *hashval); 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /ext/digest/KeccakSponge.c: -------------------------------------------------------------------------------- 1 | /* 2 | The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, 3 | Michaël Peeters and Gilles Van Assche. For more information, feedback or 4 | questions, please refer to our website: http://keccak.noekeon.org/ 5 | 6 | Implementation by the designers, 7 | hereby denoted as "the implementer". 8 | 9 | To the extent possible under law, the implementer has waived all copyright 10 | and related or neighboring rights to the source code in this file. 11 | http://creativecommons.org/publicdomain/zero/1.0/ 12 | */ 13 | 14 | #include 15 | #include "KeccakSponge.h" 16 | #include "KeccakF-1600-interface.h" 17 | #ifdef KeccakReference 18 | #include "displayIntermediateValues.h" 19 | #endif 20 | 21 | int InitSponge(spongeState *state, unsigned int rate, unsigned int capacity) 22 | { 23 | if (rate+capacity != 1600) 24 | return 1; 25 | if ((rate <= 0) || (rate >= 1600) || ((rate % 64) != 0)) 26 | return 1; 27 | KeccakInitialize(); 28 | state->rate = rate; 29 | state->capacity = capacity; 30 | state->fixedOutputLength = 0; 31 | KeccakInitializeState(state->state); 32 | memset(state->dataQueue, 0, KeccakMaximumRateInBytes); 33 | state->bitsInQueue = 0; 34 | state->squeezing = 0; 35 | state->bitsAvailableForSqueezing = 0; 36 | 37 | return 0; 38 | } 39 | 40 | void AbsorbQueue(spongeState *state) 41 | { 42 | // state->bitsInQueue is assumed to be equal to state->rate 43 | #ifdef KeccakReference 44 | displayBytes(1, "Block to be absorbed", state->dataQueue, state->rate/8); 45 | #endif 46 | #ifdef ProvideFast576 47 | if (state->rate == 576) 48 | KeccakAbsorb576bits(state->state, state->dataQueue); 49 | else 50 | #endif 51 | #ifdef ProvideFast832 52 | if (state->rate == 832) 53 | KeccakAbsorb832bits(state->state, state->dataQueue); 54 | else 55 | #endif 56 | #ifdef ProvideFast1024 57 | if (state->rate == 1024) 58 | KeccakAbsorb1024bits(state->state, state->dataQueue); 59 | else 60 | #endif 61 | #ifdef ProvideFast1088 62 | if (state->rate == 1088) 63 | KeccakAbsorb1088bits(state->state, state->dataQueue); 64 | else 65 | #endif 66 | #ifdef ProvideFast1152 67 | if (state->rate == 1152) 68 | KeccakAbsorb1152bits(state->state, state->dataQueue); 69 | else 70 | #endif 71 | #ifdef ProvideFast1344 72 | if (state->rate == 1344) 73 | KeccakAbsorb1344bits(state->state, state->dataQueue); 74 | else 75 | #endif 76 | KeccakAbsorb(state->state, state->dataQueue, state->rate/64); 77 | state->bitsInQueue = 0; 78 | } 79 | 80 | int Absorb(spongeState *state, const unsigned char *data, unsigned long long databitlen) 81 | { 82 | unsigned long long i, j, wholeBlocks; 83 | unsigned int partialBlock, partialByte; 84 | const unsigned char *curData; 85 | 86 | if ((state->bitsInQueue % 8) != 0) 87 | return 1; // Only the last call may contain a partial byte 88 | if (state->squeezing) 89 | return 1; // Too late for additional input 90 | 91 | i = 0; 92 | while(i < databitlen) { 93 | if ((state->bitsInQueue == 0) && (databitlen >= state->rate) && (i <= (databitlen-state->rate))) { 94 | wholeBlocks = (databitlen-i)/state->rate; 95 | curData = data+i/8; 96 | #ifdef ProvideFast576 97 | if (state->rate == 576) { 98 | for(j=0; jrate/8); 101 | #endif 102 | KeccakAbsorb576bits(state->state, curData); 103 | } 104 | } 105 | else 106 | #endif 107 | #ifdef ProvideFast832 108 | if (state->rate == 832) { 109 | for(j=0; jrate/8); 112 | #endif 113 | KeccakAbsorb832bits(state->state, curData); 114 | } 115 | } 116 | else 117 | #endif 118 | #ifdef ProvideFast1024 119 | if (state->rate == 1024) { 120 | for(j=0; jrate/8); 123 | #endif 124 | KeccakAbsorb1024bits(state->state, curData); 125 | } 126 | } 127 | else 128 | #endif 129 | #ifdef ProvideFast1088 130 | if (state->rate == 1088) { 131 | for(j=0; jrate/8); 134 | #endif 135 | KeccakAbsorb1088bits(state->state, curData); 136 | } 137 | } 138 | else 139 | #endif 140 | #ifdef ProvideFast1152 141 | if (state->rate == 1152) { 142 | for(j=0; jrate/8); 145 | #endif 146 | KeccakAbsorb1152bits(state->state, curData); 147 | } 148 | } 149 | else 150 | #endif 151 | #ifdef ProvideFast1344 152 | if (state->rate == 1344) { 153 | for(j=0; jrate/8); 156 | #endif 157 | KeccakAbsorb1344bits(state->state, curData); 158 | } 159 | } 160 | else 161 | #endif 162 | { 163 | for(j=0; jrate/8) { 164 | #ifdef KeccakReference 165 | displayBytes(1, "Block to be absorbed", curData, state->rate/8); 166 | #endif 167 | KeccakAbsorb(state->state, curData, state->rate/64); 168 | } 169 | } 170 | i += wholeBlocks*state->rate; 171 | } 172 | else { 173 | partialBlock = (unsigned int)(databitlen - i); 174 | if (partialBlock+state->bitsInQueue > state->rate) 175 | partialBlock = state->rate-state->bitsInQueue; 176 | partialByte = partialBlock % 8; 177 | partialBlock -= partialByte; 178 | memcpy(state->dataQueue+state->bitsInQueue/8, data+i/8, partialBlock/8); 179 | state->bitsInQueue += partialBlock; 180 | i += partialBlock; 181 | if (state->bitsInQueue == state->rate) 182 | AbsorbQueue(state); 183 | if (partialByte > 0) { 184 | unsigned char mask = (1 << partialByte)-1; 185 | state->dataQueue[state->bitsInQueue/8] = data[i/8] & mask; 186 | state->bitsInQueue += partialByte; 187 | i += partialByte; 188 | } 189 | } 190 | } 191 | return 0; 192 | } 193 | 194 | void PadAndSwitchToSqueezingPhase(spongeState *state) 195 | { 196 | // Note: the bits are numbered from 0=LSB to 7=MSB 197 | if (state->bitsInQueue + 1 == state->rate) { 198 | state->dataQueue[state->bitsInQueue/8 ] |= 1 << (state->bitsInQueue % 8); 199 | AbsorbQueue(state); 200 | memset(state->dataQueue, 0, state->rate/8); 201 | } 202 | else { 203 | memset(state->dataQueue + (state->bitsInQueue+7)/8, 0, state->rate/8 - (state->bitsInQueue+7)/8); 204 | state->dataQueue[state->bitsInQueue/8 ] |= 1 << (state->bitsInQueue % 8); 205 | } 206 | state->dataQueue[(state->rate-1)/8] |= 1 << ((state->rate-1) % 8); 207 | AbsorbQueue(state); 208 | 209 | #ifdef KeccakReference 210 | displayText(1, "--- Switching to squeezing phase ---"); 211 | #endif 212 | #ifdef ProvideFast1024 213 | if (state->rate == 1024) { 214 | KeccakExtract1024bits(state->state, state->dataQueue); 215 | state->bitsAvailableForSqueezing = 1024; 216 | } 217 | else 218 | #endif 219 | { 220 | KeccakExtract(state->state, state->dataQueue, state->rate/64); 221 | state->bitsAvailableForSqueezing = state->rate; 222 | } 223 | #ifdef KeccakReference 224 | displayBytes(1, "Block available for squeezing", state->dataQueue, state->bitsAvailableForSqueezing/8); 225 | #endif 226 | state->squeezing = 1; 227 | } 228 | 229 | int Squeeze(spongeState *state, unsigned char *output, unsigned long long outputLength) 230 | { 231 | unsigned long long i; 232 | unsigned int partialBlock; 233 | 234 | if (!state->squeezing) 235 | PadAndSwitchToSqueezingPhase(state); 236 | if ((outputLength % 8) != 0) 237 | return 1; // Only multiple of 8 bits are allowed, truncation can be done at user level 238 | 239 | i = 0; 240 | while(i < outputLength) { 241 | if (state->bitsAvailableForSqueezing == 0) { 242 | KeccakPermutation(state->state); 243 | #ifdef ProvideFast1024 244 | if (state->rate == 1024) { 245 | KeccakExtract1024bits(state->state, state->dataQueue); 246 | state->bitsAvailableForSqueezing = 1024; 247 | } 248 | else 249 | #endif 250 | { 251 | KeccakExtract(state->state, state->dataQueue, state->rate/64); 252 | state->bitsAvailableForSqueezing = state->rate; 253 | } 254 | #ifdef KeccakReference 255 | displayBytes(1, "Block available for squeezing", state->dataQueue, state->bitsAvailableForSqueezing/8); 256 | #endif 257 | } 258 | partialBlock = state->bitsAvailableForSqueezing; 259 | if ((unsigned long long)partialBlock > outputLength - i) 260 | partialBlock = (unsigned int)(outputLength - i); 261 | memcpy(output+i/8, state->dataQueue+(state->rate-state->bitsAvailableForSqueezing)/8, partialBlock/8); 262 | state->bitsAvailableForSqueezing -= partialBlock; 263 | i += partialBlock; 264 | } 265 | return 0; 266 | } 267 | -------------------------------------------------------------------------------- /ext/digest/KeccakSponge.h: -------------------------------------------------------------------------------- 1 | /* 2 | The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, 3 | Michaël Peeters and Gilles Van Assche. For more information, feedback or 4 | questions, please refer to our website: http://keccak.noekeon.org/ 5 | 6 | Implementation by the designers, 7 | hereby denoted as "the implementer". 8 | 9 | To the extent possible under law, the implementer has waived all copyright 10 | and related or neighboring rights to the source code in this file. 11 | http://creativecommons.org/publicdomain/zero/1.0/ 12 | */ 13 | 14 | #ifndef _KeccakSponge_h_ 15 | #define _KeccakSponge_h_ 16 | 17 | #define KeccakPermutationSize 1600 18 | #define KeccakPermutationSizeInBytes (KeccakPermutationSize/8) 19 | #define KeccakMaximumRate 1536 20 | #define KeccakMaximumRateInBytes (KeccakMaximumRate/8) 21 | 22 | #if defined(__GNUC__) 23 | #define ALIGN __attribute__ ((aligned(32))) 24 | #elif defined(_MSC_VER) 25 | #define ALIGN __declspec(align(32)) 26 | #else 27 | #define ALIGN 28 | #endif 29 | 30 | ALIGN typedef struct spongeStateStruct { 31 | ALIGN unsigned char state[KeccakPermutationSizeInBytes]; 32 | ALIGN unsigned char dataQueue[KeccakMaximumRateInBytes]; 33 | unsigned int rate; 34 | unsigned int capacity; 35 | unsigned int bitsInQueue; 36 | unsigned int fixedOutputLength; 37 | int squeezing; 38 | unsigned int bitsAvailableForSqueezing; 39 | } spongeState; 40 | 41 | /** 42 | * Function to initialize the state of the Keccak[r, c] sponge function. 43 | * The sponge function is set to the absorbing phase. 44 | * @param state Pointer to the state of the sponge function to be initialized. 45 | * @param rate The value of the rate r. 46 | * @param capacity The value of the capacity c. 47 | * @pre One must have r+c=1600 and the rate a multiple of 64 bits in this implementation. 48 | * @return Zero if successful, 1 otherwise. 49 | */ 50 | int InitSponge(spongeState *state, unsigned int rate, unsigned int capacity); 51 | /** 52 | * Function to give input data for the sponge function to absorb. 53 | * @param state Pointer to the state of the sponge function initialized by InitSponge(). 54 | * @param data Pointer to the input data. 55 | * When @a databitLen is not a multiple of 8, the last bits of data must be 56 | * in the least significant bits of the last byte. 57 | * @param databitLen The number of input bits provided in the input data. 58 | * @pre In the previous call to Absorb(), databitLen was a multiple of 8. 59 | * @pre The sponge function must be in the absorbing phase, 60 | * i.e., Squeeze() must not have been called before. 61 | * @return Zero if successful, 1 otherwise. 62 | */ 63 | int Absorb(spongeState *state, const unsigned char *data, unsigned long long databitlen); 64 | /** 65 | * Function to squeeze output data from the sponge function. 66 | * If the sponge function was in the absorbing phase, this function 67 | * switches it to the squeezing phase. 68 | * @param state Pointer to the state of the sponge function initialized by InitSponge(). 69 | * @param output Pointer to the buffer where to store the output data. 70 | * @param outputLength The number of output bits desired. 71 | * It must be a multiple of 8. 72 | * @return Zero if successful, 1 otherwise. 73 | */ 74 | int Squeeze(spongeState *state, unsigned char *output, unsigned long long outputLength); 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /ext/digest/brg_endian.h: -------------------------------------------------------------------------------- 1 | /* 2 | --------------------------------------------------------------------------- 3 | Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. 4 | 5 | LICENSE TERMS 6 | 7 | The redistribution and use of this software (with or without changes) 8 | is allowed without the payment of fees or royalties provided that: 9 | 10 | 1. source code distributions include the above copyright notice, this 11 | list of conditions and the following disclaimer; 12 | 13 | 2. binary distributions include the above copyright notice, this list 14 | of conditions and the following disclaimer in their documentation; 15 | 16 | 3. the name of the copyright holder is not used to endorse products 17 | built using this software without specific written permission. 18 | 19 | DISCLAIMER 20 | 21 | This software is provided 'as is' with no explicit or implied warranties 22 | in respect of its properties, including, but not limited to, correctness 23 | and/or fitness for purpose. 24 | --------------------------------------------------------------------------- 25 | Issue Date: 20/12/2007 26 | Changes for ARM 9/9/2010 27 | */ 28 | 29 | #ifndef _BRG_ENDIAN_H 30 | #define _BRG_ENDIAN_H 31 | 32 | #define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ 33 | #define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ 34 | 35 | #if 0 36 | /* Include files where endian defines and byteswap functions may reside */ 37 | #if defined( __sun ) 38 | # include 39 | #elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ ) 40 | # include 41 | #elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \ 42 | defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ ) 43 | # include 44 | #elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ ) 45 | # if !defined( __MINGW32__ ) && !defined( _AIX ) 46 | # include 47 | # if !defined( __BEOS__ ) 48 | # include 49 | # endif 50 | # endif 51 | #endif 52 | #endif 53 | 54 | /* Now attempt to set the define for platform byte order using any */ 55 | /* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */ 56 | /* seem to encompass most endian symbol definitions */ 57 | 58 | #if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN ) 59 | # if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN 60 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 61 | # elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN 62 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 63 | # endif 64 | #elif defined( BIG_ENDIAN ) 65 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 66 | #elif defined( LITTLE_ENDIAN ) 67 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 68 | #endif 69 | 70 | #if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN ) 71 | # if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN 72 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 73 | # elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN 74 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 75 | # endif 76 | #elif defined( _BIG_ENDIAN ) 77 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 78 | #elif defined( _LITTLE_ENDIAN ) 79 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 80 | #endif 81 | 82 | #if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN ) 83 | # if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN 84 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 85 | # elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN 86 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 87 | # endif 88 | #elif defined( __BIG_ENDIAN ) 89 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 90 | #elif defined( __LITTLE_ENDIAN ) 91 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 92 | #endif 93 | 94 | #if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ ) 95 | # if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__ 96 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 97 | # elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__ 98 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 99 | # endif 100 | #elif defined( __BIG_ENDIAN__ ) 101 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 102 | #elif defined( __LITTLE_ENDIAN__ ) 103 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 104 | #endif 105 | 106 | /* if the platform byte order could not be determined, then try to */ 107 | /* set this define using common machine defines */ 108 | #if !defined(PLATFORM_BYTE_ORDER) 109 | 110 | #if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \ 111 | defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \ 112 | defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \ 113 | defined( vax ) || defined( vms ) || defined( VMS ) || \ 114 | defined( __VMS ) || defined( _M_X64 ) 115 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 116 | 117 | #elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \ 118 | defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \ 119 | defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \ 120 | defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \ 121 | defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \ 122 | defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \ 123 | defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX ) 124 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 125 | 126 | #elif defined(__arm__) 127 | # ifdef __BIG_ENDIAN 128 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 129 | # else 130 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 131 | # endif 132 | #elif 1 /* **** EDIT HERE IF NECESSARY **** */ 133 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN 134 | #elif 0 /* **** EDIT HERE IF NECESSARY **** */ 135 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN 136 | #else 137 | # error Please edit lines 132 or 134 in brg_endian.h to set the platform byte order 138 | #endif 139 | 140 | #endif 141 | 142 | #endif 143 | -------------------------------------------------------------------------------- /ext/digest/displayIntermediateValues.c: -------------------------------------------------------------------------------- 1 | /* 2 | The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, 3 | Michaël Peeters and Gilles Van Assche. For more information, feedback or 4 | questions, please refer to our website: http://keccak.noekeon.org/ 5 | 6 | Implementation by the designers, 7 | hereby denoted as "the implementer". 8 | 9 | To the extent possible under law, the implementer has waived all copyright 10 | and related or neighboring rights to the source code in this file. 11 | http://creativecommons.org/publicdomain/zero/1.0/ 12 | */ 13 | 14 | #include 15 | #include "displayIntermediateValues.h" 16 | #include "KeccakNISTInterface.h" 17 | 18 | FILE *intermediateValueFile = 0; 19 | int displayLevel = 0; 20 | 21 | void displaySetIntermediateValueFile(FILE *f) 22 | { 23 | intermediateValueFile = f; 24 | } 25 | 26 | void displaySetLevel(int level) 27 | { 28 | displayLevel = level; 29 | } 30 | 31 | void displayBytes(int level, const char *text, const unsigned char *bytes, unsigned int size) 32 | { 33 | unsigned int i; 34 | 35 | if ((intermediateValueFile) && (level <= displayLevel)) { 36 | fprintf(intermediateValueFile, "%s:\n", text); 37 | for(i=0; i> iBit) & 0x01) != 0); 57 | } 58 | fprintf(intermediateValueFile, "\n"); 59 | fprintf(intermediateValueFile, "\n"); 60 | } 61 | } 62 | 63 | void displayStateAsBytes(int level, const char *text, const unsigned char *state) 64 | { 65 | displayBytes(level, text, state, KeccakPermutationSizeInBytes); 66 | } 67 | 68 | void displayStateAs32bitWords(int level, const char *text, const unsigned int *state) 69 | { 70 | unsigned int i; 71 | 72 | if ((intermediateValueFile) && (level <= displayLevel)) { 73 | fprintf(intermediateValueFile, "%s:\n", text); 74 | for(i=0; i> 32)); 92 | fprintf(intermediateValueFile, "%08X", (unsigned int)(state[i] & 0xFFFFFFFFULL)); 93 | if ((i%5) == 4) 94 | fprintf(intermediateValueFile, "\n"); 95 | else 96 | fprintf(intermediateValueFile, " "); 97 | } 98 | } 99 | } 100 | 101 | void displayRoundNumber(int level, unsigned int i) 102 | { 103 | if ((intermediateValueFile) && (level <= displayLevel)) { 104 | fprintf(intermediateValueFile, "\n"); 105 | fprintf(intermediateValueFile, "--- Round %d ---\n", i); 106 | fprintf(intermediateValueFile, "\n"); 107 | } 108 | } 109 | 110 | void displayText(int level, const char *text) 111 | { 112 | if ((intermediateValueFile) && (level <= displayLevel)) { 113 | fprintf(intermediateValueFile, text); 114 | fprintf(intermediateValueFile, "\n"); 115 | fprintf(intermediateValueFile, "\n"); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /ext/digest/displayIntermediateValues.h: -------------------------------------------------------------------------------- 1 | /* 2 | The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, 3 | Michaël Peeters and Gilles Van Assche. For more information, feedback or 4 | questions, please refer to our website: http://keccak.noekeon.org/ 5 | 6 | Implementation by the designers, 7 | hereby denoted as "the implementer". 8 | 9 | To the extent possible under law, the implementer has waived all copyright 10 | and related or neighboring rights to the source code in this file. 11 | http://creativecommons.org/publicdomain/zero/1.0/ 12 | */ 13 | 14 | #ifndef _displayIntermediateValues_h_ 15 | #define _displayIntermediateValues_h_ 16 | 17 | #include 18 | 19 | void displaySetIntermediateValueFile(FILE *f); 20 | void displaySetLevel(int level); 21 | void displayBytes(int level, const char *text, const unsigned char *bytes, unsigned int size); 22 | void displayBits(int level, const char *text, const unsigned char *data, unsigned int size, int MSBfirst); 23 | void displayStateAsBytes(int level, const char *text, const unsigned char *state); 24 | void displayStateAs32bitWords(int level, const char *text, const unsigned int *state); 25 | void displayStateAs64bitWords(int level, const char *text, const unsigned long long int *state); 26 | void displayRoundNumber(int level, unsigned int i); 27 | void displayText(int level, const char *text); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /ext/digest/extconf.rb: -------------------------------------------------------------------------------- 1 | require 'mkmf' 2 | 3 | have_header('ruby/digest.h') 4 | have_func('rb_str_set_len') 5 | 6 | $CFLAGS << " -fvisibility=hidden" 7 | create_makefile('digest/sha3') 8 | -------------------------------------------------------------------------------- /ext/digest/sha3.c: -------------------------------------------------------------------------------- 1 | #include "ruby.h" 2 | #ifdef HAVE_RUBY_DIGEST_H 3 | #include "ruby/digest.h" 4 | #else 5 | #include "digest.h" 6 | #endif 7 | #include "KeccakNISTInterface.h" 8 | 9 | #define MAX_DIGEST_SIZE 64 10 | #define DEFAULT_DIGEST_LEN 512 11 | 12 | static int sha3_init_func(hashState *ctx); 13 | static void sha3_update_func(hashState *ctx, unsigned char *str, size_t len); 14 | static int sha3_finish_func(hashState *ctx, unsigned char *digest); 15 | 16 | /* 17 | Metadata definition for the SHA3 algorithm. 18 | Defines the Version, sizes for block and digest as well as 19 | the entry points for the algorithms 20 | */ 21 | static rb_digest_metadata_t sha3 = { 22 | RUBY_DIGEST_API_VERSION, 23 | DEFAULT_DIGEST_LEN, 24 | KeccakPermutationSize - (2 * DEFAULT_DIGEST_LEN), //size of blocks 25 | sizeof(hashState), //size of context for the object we'll be passed in below functions. 26 | (rb_digest_hash_init_func_t)sha3_init_func, 27 | (rb_digest_hash_update_func_t)sha3_update_func, 28 | (rb_digest_hash_finish_func_t)sha3_finish_func, 29 | }; 30 | 31 | /* Initialization function for the algorithm, 32 | gets called during allocation of the digest object. 33 | we override initialize to do custom hash size, so we don't care too much here. 34 | */ 35 | static int 36 | sha3_init_func(hashState *ctx) { 37 | // Just return a 1 ' successful' we override the init function 38 | // so this is not necessary 39 | // the base class alloc calls this to initialize the algorithm 40 | return 1; 41 | } 42 | 43 | /* Update function, take the current context and add str to it */ 44 | static void 45 | sha3_update_func(hashState *ctx, unsigned char *str, size_t len) { 46 | Update(ctx, str, len * 8); 47 | } 48 | 49 | /* Finish the hash calculation and return the finished string */ 50 | static int 51 | sha3_finish_func(hashState *ctx, unsigned char *digest) { 52 | Final(ctx, digest); 53 | return 1; 54 | } 55 | 56 | /* Ruby method. Digest::SHA3#finish() 57 | * No Arguments 58 | * @returns [String] Encoded Digest String 59 | */ 60 | static VALUE 61 | rb_sha3_finish(VALUE self) { 62 | hashState *ctx; 63 | VALUE digest; 64 | 65 | ctx = (hashState *)RTYPEDDATA_DATA(self); 66 | digest = rb_str_new(0, ctx->capacity / 2 / 8); 67 | sha3_finish_func(ctx, (unsigned char *)RSTRING_PTR(digest)); 68 | 69 | return digest; 70 | } 71 | 72 | /* :nodoc: private method 73 | * initialize the ctx with the bitlength 74 | */ 75 | static void 76 | sha3_init(hashState *ctx, size_t bitlen) { 77 | switch (Init(ctx, bitlen)) { 78 | case SUCCESS: 79 | return; 80 | case FAIL: 81 | rb_raise(rb_eRuntimeError, "Unknown error"); 82 | case BAD_HASHLEN: 83 | rb_raise(rb_eArgError, "Bad hash length (must be 0, 224, 256, 384 or 512)"); 84 | default: 85 | rb_raise(rb_eRuntimeError, "Unknown error code"); 86 | } 87 | } 88 | 89 | /* Ruby method. Digest::SHA3.new(hashlen) 90 | * @param hashlen The length of hash, only supports 224, 256, 384 or 512 91 | * @returns [Digest::SHA3] new object. 92 | */ 93 | static VALUE 94 | rb_sha3_initialize(int argc, VALUE *argv, VALUE self) { 95 | hashState *ctx; 96 | VALUE hashlen; 97 | int i_hashlen; 98 | 99 | if (rb_scan_args(argc, argv, "01", &hashlen) == 0) { 100 | i_hashlen = DEFAULT_DIGEST_LEN; 101 | } else { 102 | i_hashlen = NUM2INT(hashlen); 103 | } 104 | if ( i_hashlen == 0) { 105 | rb_raise(rb_eArgError, "Unsupported hash length"); 106 | } 107 | 108 | ctx = (hashState *)RTYPEDDATA_DATA(self); 109 | sha3_init(ctx, i_hashlen); 110 | 111 | return rb_call_super(0, NULL); 112 | } 113 | 114 | /* Ruby method. Digest::SHA3#digest_length 115 | * @returns [Numeric] Length of the digest. 116 | */ 117 | static VALUE 118 | rb_sha3_digest_length(VALUE self) { 119 | hashState *ctx; 120 | 121 | ctx = (hashState *)RTYPEDDATA_DATA(self); 122 | return INT2FIX(ctx->capacity / 2 / 8); 123 | } 124 | 125 | /* Ruby method. Digest::SHA3#block_length 126 | * @returns [Numeric] Length of blocks in this digest. 127 | */ 128 | static VALUE 129 | rb_sha3_block_length(VALUE self) { 130 | hashState *ctx; 131 | 132 | ctx = (hashState *)RTYPEDDATA_DATA(self); 133 | return INT2FIX(ctx->rate / 8); 134 | } 135 | 136 | void __attribute__((visibility("default"))) 137 | Init_sha3() { 138 | VALUE mDigest, cDigest_Base, cSHA3; 139 | 140 | rb_require("digest"); 141 | 142 | mDigest = rb_path2class("Digest"); 143 | cDigest_Base = rb_path2class("Digest::Base"); 144 | 145 | cSHA3 = rb_define_class_under(mDigest, "SHA3", cDigest_Base); 146 | 147 | rb_iv_set(cSHA3, "metadata", Data_Wrap_Struct(0, 0, 0, (void *)&sha3)); 148 | 149 | rb_define_method(cSHA3, "initialize", rb_sha3_initialize, -1); 150 | rb_define_method(cSHA3, "digest_length", rb_sha3_digest_length, 0); 151 | rb_define_method(cSHA3, "block_length", rb_sha3_block_length, 0); 152 | rb_define_method(cSHA3, "finish", rb_sha3_finish, 0); 153 | } 154 | -------------------------------------------------------------------------------- /lib/digest/sha3/version.rb: -------------------------------------------------------------------------------- 1 | module Digest 2 | class SHA3 3 | module Version 4 | STRING = "1.1.0" 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /test/data/README: -------------------------------------------------------------------------------- 1 | From KeccakKAT-3.zip 2 | 3 | http://keccak.noekeon.org/KeccakKAT-3.zip 4 | -------------------------------------------------------------------------------- /test/generate_tests.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # This will generate a test suite. 4 | # Based on python-sha3's test suite. 5 | 6 | FILES = [ 7 | ['test/data/ShortMsgKAT_224.txt', 224], 8 | ['test/data/ShortMsgKAT_256.txt', 256], 9 | ['test/data/ShortMsgKAT_384.txt', 384], 10 | ['test/data/ShortMsgKAT_512.txt', 512], 11 | ['test/data/LongMsgKAT_224.txt', 224], 12 | ] 13 | 14 | def generate 15 | puts %Q{ 16 | # encoding: binary 17 | # This file generated by generate_tests.rb 18 | 19 | require 'test/unit' 20 | 21 | class SHA3Tests < Test::Unit::TestCase 22 | } 23 | 24 | FILES.each do |path, hashlen| 25 | contents = File.read(path).split('Len = ') 26 | contents.each do |test| 27 | lines = test.split("\n") 28 | if !lines.empty? && lines[0] !~ /^#/ 29 | length = lines[0].to_i 30 | if length % 8 == 0 && length != 0 31 | msg_raw = [lines[1].split(' = ').last].pack("H*") 32 | md = lines[2].split(' = ').last.downcase 33 | name = File.basename(path).split('.')[0] 34 | puts %Q{ 35 | def test_#{name}_#{length} 36 | inst = Digest::SHA3.new(#{hashlen}) 37 | inst.update(#{msg_raw.inspect}) 38 | assert_equal #{md.inspect}, inst.hexdigest 39 | end 40 | } 41 | end 42 | end 43 | end 44 | end 45 | 46 | puts "end" 47 | end 48 | 49 | generate 50 | -------------------------------------------------------------------------------- /test/test_all.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift(File.expand_path("lib")) 2 | $LOAD_PATH.unshift(File.expand_path("ext")) 3 | require 'digest/sha3' 4 | require File.expand_path('test/test_usage') 5 | require File.expand_path('test/test_vectors') 6 | -------------------------------------------------------------------------------- /test/test_usage.rb: -------------------------------------------------------------------------------- 1 | require 'test/unit' 2 | 3 | class SHA3UsageTest < Test::Unit::TestCase 4 | def init(hashsize = 512) 5 | @digest = Digest::SHA3.new(hashsize) 6 | end 7 | 8 | def test_copy 9 | a = init(224) 10 | a.update('foo') 11 | b = a.dup 12 | assert_equal b.digest, a.digest 13 | b.update('bar') 14 | assert_not_equal b.digest, a.digest 15 | end 16 | 17 | def test_class_methods 18 | assert_equal 'a9cab59eb40a10b246290f2d6086e32e3689faf1d26b470c899f2802', 19 | Digest::SHA3.hexdigest("\xcc", 224) 20 | end 21 | 22 | def test_update 23 | a = init(224) 24 | a.update("\xcc") 25 | assert_equal 'a9cab59eb40a10b246290f2d6086e32e3689faf1d26b470c899f2802', a.hexdigest 26 | end 27 | 28 | def test_updates 29 | a = init(224) 30 | a.update("\x21") 31 | a.update("\xf1\x34") 32 | a.update("\xac\x57") 33 | assert_equal '5573da2b02216a860389a581f6e9fb8d805e9e02f6fa911701eee298', a.hexdigest 34 | end 35 | 36 | def test_empty_224 37 | a = init(224) 38 | assert_equal 'f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd', a.hexdigest 39 | end 40 | 41 | def test_empty_256 42 | a = init(256) 43 | assert_equal 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', a.hexdigest 44 | end 45 | 46 | def test_empty_384 47 | a = init(384) 48 | assert_equal '2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff', a.hexdigest() 49 | end 50 | 51 | def test_empty_512 52 | a = init(512) 53 | assert_equal '0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e', a.hexdigest 54 | end 55 | end 56 | --------------------------------------------------------------------------------