Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to argon2id for storing passwords #564

Open
wants to merge 20 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .earthlyignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
lib/argon2/build
lib/argon2/bin
lib/argon2/ndll
lib/argon2/obj
57 changes: 50 additions & 7 deletions Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ neko-latest:
RUN tar --strip-components=1 -xf "$FILENAME" -C neko
SAVE ARTIFACT neko/*

INSTALL_NEKO:
COMMAND
ARG NEKOPATH=/neko
COPY +neko-latest/* "$NEKOPATH/"
ARG PREFIX=/usr/local
RUN bash -c "ln -s \"$NEKOPATH\"/{neko,nekoc,nekoml,nekotools} \"$PREFIX/bin/\""
RUN bash -c "ln -s \"$NEKOPATH\"/libneko.* \"$PREFIX/lib/\""
RUN bash -c "ln -s \"$NEKOPATH\"/neko.h \"$PREFIX/include/\""
RUN mkdir -p "$PREFIX/lib/neko/"
RUN bash -c "ln -s \"$NEKOPATH\"/*.ndll \"$PREFIX/lib/neko/\""
RUN ldconfig

haxe-latest:
ARG FILENAME=haxe_2022-08-09_development_779b005.tar.gz
RUN haxeArch=$(case "$TARGETARCH" in \
Expand Down Expand Up @@ -106,10 +118,7 @@ devcontainer-base:
&& rm -rf /var/lib/apt/lists/*

# install neko nightly
COPY +neko-latest/neko /usr/bin/neko
COPY +neko-latest/libneko.so* /usr/lib/
RUN mkdir -p /usr/lib/neko/
COPY +neko-latest/*.ndll /usr/lib/neko/
DO +INSTALL_NEKO
RUN neko -version

# install haxe nightly
Expand Down Expand Up @@ -234,6 +243,7 @@ haxelib-deps:
USER $USERNAME
COPY --chown=$USER_UID:$USER_GID libs.hxml run.n .
COPY --chown=$USER_UID:$USER_GID lib/record-macros lib/record-macros
COPY --chown=$USER_UID:$USER_GID lib/argon2 lib/argon2
RUN mkdir -p haxelib_global
RUN neko run.n setup haxelib_global
RUN haxe libs.hxml && rm haxelib_global/*.zip
Expand Down Expand Up @@ -346,11 +356,32 @@ aws-ndll:
FROM +haxelib-deps
SAVE ARTIFACT /workspace/haxelib_global/aws-sdk-neko/*/ndll/Linux64/aws.ndll

argon2-ndll:
# install build-essential, cmake, and neko
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y \
build-essential \
&& rm -r /var/lib/apt/lists/*

RUN curl -fsSL "https://github.com/Kitware/CMake/releases/download/v3.24.0/cmake-3.24.0-linux-x86_64.sh" -o cmake-install.sh \
&& sh cmake-install.sh --skip-license --prefix /usr/local \
&& rm cmake-install.sh

DO +INSTALL_NEKO
RUN neko -version

COPY lib/argon2 lib/argon2
RUN mkdir lib/argon2/build
RUN cmake -B lib/argon2/build -S lib/argon2
RUN make -C lib/argon2/build
SAVE ARTIFACT lib/argon2/build/argon2.ndll

haxelib-server-builder:
FROM haxe:3.4

WORKDIR /workspace
COPY lib/record-macros lib/record-macros
COPY lib/argon2 lib/argon2
COPY --chown=$USER_UID:$USER_GID +node-modules-dev/node_modules node_modules
COPY --chown=$USER_UID:$USER_GID +dts2hx-externs/dts2hx-generated lib/dts2hx-generated
COPY --chown=$USER_UID:$USER_GID +haxelib-deps/haxelib_global haxelib_global
Expand Down Expand Up @@ -391,13 +422,21 @@ haxelib-server-tasks:
RUN haxe server_tasks.hxml
SAVE ARTIFACT www/tasks.n

haxelib-server-api-3.0:
FROM +haxelib-server-builder
COPY server_api_3.0.hxml server_each.hxml .
COPY src src
COPY hx3compat hx3compat
RUN haxe server_api_3.0.hxml
SAVE ARTIFACT www/api/3.0/index.n

haxelib-server-api:
FROM +haxelib-server-builder
COPY server_api.hxml server_each.hxml .
COPY src src
COPY hx3compat hx3compat
RUN haxe server_api.hxml
SAVE ARTIFACT www/api/3.0/index.n
SAVE ARTIFACT www/api/4.0/index.n

haxelib-server-www-js:
FROM +devcontainer-base
Expand Down Expand Up @@ -454,6 +493,7 @@ haxelib-server:
&& apachectl stop

COPY +aws-ndll/aws.ndll /usr/lib/x86_64-linux-gnu/neko/aws.ndll
COPY +argon2-ndll/argon2.ndll /usr/lib/x86_64-linux-gnu/neko/argon2.ndll

WORKDIR /src

Expand All @@ -477,7 +517,8 @@ haxelib-server:
COPY +haxelib-server-website-highlighter/highlighter.js www/js/highlighter.js
COPY +haxelib-server-website/index.n www/index.n
COPY +haxelib-server-tasks/tasks.n www/tasks.n
COPY +haxelib-server-api/index.n www/api/3.0/index.n
COPY +haxelib-server-api-3.0/index.n www/api/3.0/index.n
COPY +haxelib-server-api/index.n www/api/4.0/index.n

EXPOSE 80

Expand Down Expand Up @@ -518,13 +559,15 @@ ci-tests:
COPY hx3compat hx3compat
COPY lib/node-sys-db lib/node-sys-db
COPY lib/record-macros lib/record-macros
COPY lib/argon2 lib/argon2
COPY +argon2-ndll/argon2.ndll argon2.ndll
COPY src src
COPY www www
COPY test test
COPY *.hxml .

# for package.hxml
COPY haxelib.json README.md .
COPY haxelib.json README.md .
COPY +run.n/run.n .

COPY +ci-runner/ci.n bin/ci.n
Expand Down
4 changes: 3 additions & 1 deletion integration_tests.hxml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
-cp src
-cp test
-lib hx3compat
-lib record-macros
-lib argon2
-main IntegrationTests
-neko bin/integration_tests.n
-neko bin/integration_tests.n
6 changes: 6 additions & 0 deletions lib/argon2/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.n
*.ndll

obj/
bin/
build/
46 changes: 46 additions & 0 deletions lib/argon2/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
cmake_minimum_required(VERSION 3.23)

project(Argon2Ndll C)

include(ExternalProject)

set(ARGON2_LIB ${CMAKE_BINARY_DIR}/libs/src/Argon2/libargon2.a)
set(ARGON2_INCLUDE ${CMAKE_BINARY_DIR}/libs/src/Argon2/include)

ExternalProject_Add(Argon2
PREFIX ${CMAKE_BINARY_DIR}/libs
DOWNLOAD_DIR ${CMAKE_BINARY_DIR}/libs/download
URL https://github.com/P-H-C/phc-winner-argon2/archive/refs/tags/20190702.tar.gz
URL_HASH SHA256=daf972a89577f8772602bf2eb38b6a3dd3d922bf5724d45e7f9589b5e830442c
BUILD_COMMAND cd ${CMAKE_BINARY_DIR}/libs/src/Argon2 && CFLAGS=-fPIC make
CONFIGURE_COMMAND echo skip config
INSTALL_COMMAND echo skip install
BYPRODUCTS ${ARGON2_LIB}
)

add_custom_command(
OUTPUT ${ARGON2_INCLUDE}/argon2.h
DEPENDS Argon2
)

add_custom_command(
OUTPUT ${ARGON2_LIB}
DEPENDS Argon2
)

add_library(argon2.ndll MODULE native/argon2.c)

target_include_directories(argon2.ndll PRIVATE ${ARGON2_INCLUDE})
target_link_libraries(argon2.ndll libneko.so ${ARGON2_LIB})

set_target_properties(argon2.ndll
PROPERTIES
PREFIX ""
OUTPUT_NAME argon2
SUFFIX .ndll
)

install(
TARGETS argon2.ndll
DESTINATION ${CMAKE_SOURCE_DIR}/ndll/Linux64
)
12 changes: 12 additions & 0 deletions lib/argon2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Argon2 Neko bindings

## Building

To build the ndll file, run the following commands:

```sh
mkdir build
cd build
cmake ..
make
```
7 changes: 7 additions & 0 deletions lib/argon2/haxelib.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "argon2",
"description": "Neko wrapper for C argon2 implementation",
"version": "0.0.0",
"classPath": "src",
"license": "MIT"
}
70 changes: 70 additions & 0 deletions lib/argon2/native/argon2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include <neko.h>
#include <stdio.h>

#include "argon2.h"

#define HASHLEN 32

static void handle_error(int rc) {
buffer b = alloc_buffer("Argon2 Error: ");
buffer_append(b, argon2_error_message(rc));
buffer_append(b, "\n");
val_throw(buffer_to_string(b));
}

value generate_argon2id_raw_hash(value time_cost, value memory_cost, value parallelism, value password, value salt) {
printf("hello\n");
val_check(time_cost, int);
val_check(memory_cost, int);
val_check(parallelism, int);
val_check(password, string);
val_check(salt, string);

value hash = alloc_empty_string(HASHLEN);

int rc = argon2id_hash_raw(val_int(time_cost), val_int(memory_cost), val_int(parallelism), val_string(password), val_strlen(password), val_string(salt), val_strlen(salt), val_string(hash), HASHLEN);
if (rc != ARGON2_OK) {
handle_error(rc);
}

return hash;
}

value generate_argon2id_hash(value time_cost, value memory_cost, value parallelism, value password, value salt) {
val_check(time_cost, int);
val_check(memory_cost, int);
val_check(parallelism, int);
val_check(password, string);
val_check(salt, string);

size_t salt_len = val_strlen(salt);
size_t password_len = val_strlen(password);
size_t encoded_len = argon2_encodedlen(val_int(time_cost), val_int(memory_cost), val_int(parallelism), salt_len, HASHLEN, Argon2_id);

// encoded_len takes into account null terminator, however, alloc_empty_string adds an extra byte for that anyway
value hash_string = alloc_empty_string(encoded_len - 1);

int rc = argon2id_hash_encoded(val_int(time_cost), val_int(memory_cost), val_int(parallelism), val_string(password), password_len, val_string(salt), salt_len, HASHLEN, val_string(hash_string), encoded_len);
if (rc != ARGON2_OK) {
handle_error(rc);
}

return hash_string;
}

value verify_argon2id(value hash, value password) {
val_check(hash, string);
val_check(password, string);

int rc = argon2id_verify(val_string(hash), val_string(password), val_strlen(password));
if (rc == ARGON2_OK)
return val_true;
if (rc == ARGON2_VERIFY_MISMATCH)
return val_false;
handle_error(rc);
return val_false;
}

DEFINE_PRIM(generate_argon2id_raw_hash, 5);
DEFINE_PRIM(generate_argon2id_hash, 5);
DEFINE_PRIM(verify_argon2id, 2);
21 changes: 21 additions & 0 deletions lib/argon2/src/argon2/Argon2id.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package argon2;

import haxe.io.Bytes;

class Argon2id {
public static function generateHash(password:String, salt:Bytes, timeCost:Int, memoryCost:Int, parallelism:Int):String {
return new String(untyped generate_argon2id_hash(timeCost, memoryCost, parallelism, password.__s, salt.getData()));
}

public static function generateRawHash(password:String, salt:Bytes, timeCost:Int, memoryCost:Int, parallelism:Int) {
return new String(untyped generate_argon2id_raw_hash(timeCost, memoryCost, parallelism, password.__s, salt.getData()));
}

public static function verify(hash:String, password:String) {
return untyped verify_argon2id(hash.__s, password.__s);
}

static var generate_argon2id_hash = neko.Lib.load("argon2", "generate_argon2id_hash", 5);
static var generate_argon2id_raw_hash = neko.Lib.load("argon2", "generate_argon2id_raw_hash", 5);
static var verify_argon2id = neko.Lib.load("argon2", "verify_argon2id", 2);
}
4 changes: 4 additions & 0 deletions lib/argon2/test.hxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
--main Test
-p test
-lib argon2
--neko bin/test.n
13 changes: 13 additions & 0 deletions lib/argon2/test/Test.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import argon2.Argon2id;
import haxe.io.Bytes;

function main() {
final hash = Argon2id.generateRawHash("hello", Bytes.ofString("tesfdfdafdafsagfagahraegfaharegh"), 2, 1 << 16, 1);
trace(hash);

final hash = Argon2id.generateHash("hello", Bytes.ofString("tesfdfdafdafsagfagahraegfaharegh"), 2, 1 << 16, 1);
trace(hash);

trace(Argon2id.verify(hash, "hello"));
trace(Argon2id.verify(hash, "hi"));
}
1 change: 1 addition & 0 deletions libs.hxml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@
-cmd curl -sSLk https://lib.haxe.org/files/3.0/utest-1,9,6.zip -o haxelib_global/utest.zip && neko run.n install --always --skip-dependencies haxelib_global/utest.zip
-cmd curl -sSLk https://lib.haxe.org/files/3.0/hxnodejs-12,1,0.zip -o haxelib_global/hxnodejs.zip && neko run.n install --always --skip-dependencies haxelib_global/hxnodejs.zip
-cmd neko run.n dev record-macros lib/record-macros
-cmd neko run.n dev argon2 lib/argon2
16 changes: 9 additions & 7 deletions server_api.hxml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
-cp src
-neko www/api/3.0/index.n
-main haxelib.server.Repo
-lib aws-sdk-neko
-lib record-macros
-dce no
-D haxelib_api
-cp src
-neko www/api/4.0/index.n
-main haxelib.server.Repo
-lib aws-sdk-neko
-lib record-macros
-lib argon2
-dce no
-D haxelib-api
-D haxelib-api-version=4.0
9 changes: 9 additions & 0 deletions server_api_3.0.hxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-cp src
-neko www/api/3.0/index.n
-main haxelib.server.Repo
-lib aws-sdk-neko
-lib record-macros
-lib argon2
-dce no
-D haxelib-api
-D haxelib-api-version=3.0
3 changes: 2 additions & 1 deletion server_each.hxml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
-lib aws-sdk-neko
-lib record-macros
-lib html-haxe-code-highlighter:0.1.2
-lib argon2
-D server
-D getter_support
# https://github.com/HaxeFoundation/haxe/issues/4903
--macro keep('StringBuf')
--macro keep('StringBuf')
6 changes: 6 additions & 0 deletions skeema/.skeema
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ flavor=mysql:5.7
host=haxe-org.ct0xwjh6v08k.eu-west-1.rds.amazonaws.com
port=3306
schema=haxelib

[test]
flavor=mysql:5.7
host=localhost
port=3306
schema=haxelib
5 changes: 5 additions & 0 deletions skeema/Meta.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CREATE TABLE `Meta` (
`id` enum('') NOT NULL DEFAULT '',
`dbVersion` int(10) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2 changes: 2 additions & 0 deletions skeema/User.sql
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ CREATE TABLE `User` (
`fullname` mediumtext NOT NULL,
`email` mediumtext NOT NULL,
`pass` mediumtext NOT NULL,
`salt` binary(32) NOT NULL,
`hashmethod` mediumtext NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Loading