Skip to content

Commit

Permalink
use optimized implementations from XKCP (#8)
Browse files Browse the repository at this point in the history
* src/libkeccak: Use XKCP's optimized implementations

It looks like we were using the reference C implementation, which is not
designed for good performance.

Switch to using either the 32-bit or 64-bit optimized C implementations,
depending on the Node "arch" variable.

* Remove submodule KeccakCodePackage

* Bump minimum node version to 6.0.0

* Small improvements in src/README.md

* Add preprocessor in src/addon.cc

* Add submodle github.com/XKCP/XKCP for test vectors
  • Loading branch information
cakoose authored and fanatid committed Dec 20, 2018
1 parent 09d59ee commit a7e7b02
Show file tree
Hide file tree
Showing 35 changed files with 3,950 additions and 784 deletions.
6 changes: 3 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[submodule "keccak-src"]
path = util/KeccakCodePackage
url = https://github.com/gvanas/KeccakCodePackage.git
[submodule "util/XKCP"]
path = util/XKCP
url = https://github.com/XKCP/XKCP.git
34 changes: 27 additions & 7 deletions binding.gyp
Original file line number Diff line number Diff line change
@@ -1,19 +1,39 @@
{
"variables": {
"arch": "<!(node -p 'process.arch')",
},
"targets": [{
"target_name": "keccak",
"sources": [
"./src/addon.cc",
"./src/libkeccak/KeccakSponge.c",
"./src/libkeccak/KeccakP-1600-reference.c"
],
"conditions": [
["arch in ('arm64','ppc64','x64')",
# For known 64-bit architectures, use the implementation optimized for 64-bit CPUs.
{
"sources": [
"./src/libkeccak-64/KeccakSpongeWidth1600.c",
"./src/libkeccak-64/KeccakP-1600-opt64.c",
],
"defines": [
"LIBKECCAK=64",
],
},
# Otherwise, use the implementation optimized for 32-bit CPUs.
{
"sources": [
"./src/libkeccak-32/KeccakSpongeWidth1600.c",
"./src/libkeccak-32/KeccakP-1600-inplace32BI.c",
],
"defines": [
"LIBKECCAK=32",
],
},
],
],
"include_dirs": [
"<!(node -e \"require('nan')\")"
],
"defines": [
"KeccakP200_excluded=1",
"KeccakP400_excluded=1",
"KeccakP800_excluded=1"
],
"cflags": [
"-Wall",
"-Wno-maybe-uninitialized",
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
"coverage": "nyc tape test/index.js",
"coverage-lcov": "npm run coverage && nyc report -r lcov",
"install": "npm run rebuild || echo \"Keccak bindings compilation fail. Pure JS implementation will be used.\"",
"libkeccak": "./util/libkeccak.sh",
"lint": "standard",
"rebuild": "node-gyp rebuild",
"test": "npm run lint && npm run unit",
Expand All @@ -52,7 +51,7 @@
"tape": "^4.5.1"
},
"engines": {
"node": ">=4.0.0"
"node": ">=6.0.0"
},
"gypfile": true,
"browser": {
Expand Down
28 changes: 28 additions & 0 deletions src/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Importing Keccak C code

The XKCP project contains various implementations of Keccak-related algorithms. These are the steps to select a specific implementation and import the code into our project.

First, generate the source bundles in XKCP:

```
git clone https://github.com/XKCP/XKCP.git
cd XKCP
git checkout 58b20ec
# Edit "Makefile.build". After all the <fragment> tags, add the following two <target> tags:
<target name="node32" inherits="KeccakSpongeWidth1600 inplace1600bi"/>
<target name="node64" inherits="KeccakSpongeWidth1600 optimized1600ufull"/>
make node32.pack node64.pack
```

The source files we need are now under XKCP's "bin/.pack/npm32/" and "bin/.pack/npm64/".
- Copy those to our repo under "src/libkeccak-32" and "src/libkeccak-64".
- Update our "binding.gyp" to point to the correct ".c" files.
- Run `npm run rebuild`.

## Implementation Choice

Currently, we're using two of XKCP KeccakP[1600] implementations -- the generic 32-bit-optimized one and the generic 64-bit-optimized one.

XKCP has implementations that use CPU-specific instructions (e.g. Intel AVR) and are likely much faster. It might be worth using those.
25 changes: 24 additions & 1 deletion src/addon.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@
#include <nan.h>

extern "C" {
#include "libkeccak/KeccakSponge.h"
#if LIBKECCAK == 32
#include "libkeccak-32/KeccakSpongeWidth1600.h"
#elif LIBKECCAK == 64
#include "libkeccak-64/KeccakSpongeWidth1600.h"
#else
#error "LIBKECCAK not defined correctly"
#endif
}

class KeccakWrapper : public Nan::ObjectWrap {
Expand Down Expand Up @@ -34,8 +40,13 @@ class KeccakWrapper : public Nan::ObjectWrap {

static NAN_METHOD(Initialize) {
KeccakWrapper* obj = Nan::ObjectWrap::Unwrap<KeccakWrapper>(info.Holder());
#if (NODE_MODULE_VERSION >= NODE_7_0_MODULE_VERSION)
unsigned int rate = info[0]->IntegerValue(info.GetIsolate()->GetCurrentContext()).ToChecked();
unsigned int capacity = info[1]->IntegerValue(info.GetIsolate()->GetCurrentContext()).ToChecked();
#else
unsigned int rate = info[0]->IntegerValue();
unsigned int capacity = info[1]->IntegerValue();
#endif

// ignore return code, rate & capacity always will right because internal object
KeccakWidth1600_SpongeInitialize(&obj->sponge, rate, capacity);
Expand All @@ -53,15 +64,23 @@ class KeccakWrapper : public Nan::ObjectWrap {

static NAN_METHOD(AbsorbLastFewBits) {
KeccakWrapper* obj = Nan::ObjectWrap::Unwrap<KeccakWrapper>(info.Holder());
#if (NODE_MODULE_VERSION >= NODE_7_0_MODULE_VERSION)
unsigned char bits = info[0]->IntegerValue(info.GetIsolate()->GetCurrentContext()).ToChecked();
#else
unsigned char bits = info[0]->IntegerValue();
#endif

// ignore return code, bcause internal object
KeccakWidth1600_SpongeAbsorbLastFewBits(&obj->sponge, bits);
}

static NAN_METHOD(Squeeze) {
KeccakWrapper* obj = Nan::ObjectWrap::Unwrap<KeccakWrapper>(info.Holder());
#if (NODE_MODULE_VERSION >= NODE_7_0_MODULE_VERSION)
size_t length = info[0]->IntegerValue(info.GetIsolate()->GetCurrentContext()).ToChecked();
#else
size_t length = info[0]->IntegerValue();
#endif

v8::Local<v8::Object> buffer = Nan::NewBuffer(length).ToLocalChecked();
unsigned char* data = (unsigned char*) node::Buffer::Data(buffer);
Expand All @@ -72,7 +91,11 @@ class KeccakWrapper : public Nan::ObjectWrap {

static NAN_METHOD(Copy) {
KeccakWrapper* from = Nan::ObjectWrap::Unwrap<KeccakWrapper>(info.Holder());
#if (NODE_MODULE_VERSION >= NODE_7_0_MODULE_VERSION)
KeccakWrapper* to = Nan::ObjectWrap::Unwrap<KeccakWrapper>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());
#else
KeccakWrapper* to = Nan::ObjectWrap::Unwrap<KeccakWrapper>(info[0]->ToObject());
#endif

memcpy(&to->sponge, &from->sponge, sizeof(KeccakWidth1600_SpongeInstance));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
Implementation by Ronny Van Keer, hereby denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
For more information, feedback or questions, please refer to our website:
https://keccak.team/
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/
---
Please refer to SnP-documentation.h for more details.
*/

#ifndef _KeccakP_1600_SnP_h_
Expand All @@ -19,20 +19,17 @@ and related or neighboring rights to the source code in this file.
/** For the documentation, see SnP-documentation.h.
*/

#define KeccakP1600_implementation "64-bit reference implementation"
#define KeccakP1600_implementation "in-place 32-bit optimized implementation"
#define KeccakP1600_stateSizeInBytes 200
#define KeccakP1600_stateAlignment 8

#ifdef KeccakReference
void KeccakP1600_StaticInitialize( void );
#else
#define KeccakP1600_StaticInitialize()
#endif
void KeccakP1600_Initialize(void *state);
void KeccakP1600_AddByte(void *state, unsigned char data, unsigned int offset);
void KeccakP1600_AddBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length);
void KeccakP1600_OverwriteBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length);
void KeccakP1600_OverwriteWithZeroes(void *state, unsigned int byteCount);
void KeccakP1600_Permute_Nrounds(void *state, unsigned int nrounds);
void KeccakP1600_Permute_12rounds(void *state);
void KeccakP1600_Permute_24rounds(void *state);
void KeccakP1600_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length);
Expand Down
Loading

0 comments on commit a7e7b02

Please sign in to comment.