Skip to content

Commit

Permalink
merge
Browse files Browse the repository at this point in the history
  • Loading branch information
kkmanos committed Aug 31, 2023
2 parents 84fd756 + 4889b98 commit 1d12d26
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
contents: read # To check out repo
packages: read # To read NPM registry

uses: gunet/wallet-ecosystem/.github/workflows/docker-build-push.yml@npmrc-template
uses: gunet/wallet-ecosystem/.github/workflows/docker-build-push.yml@master
with:
image-tag: ghcr.io/gunet/wallet-backend:latest
docker-push: false
2 changes: 1 addition & 1 deletion .github/workflows/docker-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
contents: read # To check out repo
packages: write # To read NPM registry and push Docker image

uses: gunet/wallet-ecosystem/.github/workflows/docker-build-push.yml@npmrc-template
uses: gunet/wallet-ecosystem/.github/workflows/docker-build-push.yml@master
with:
image-tag: ghcr.io/gunet/wallet-backend:latest
docker-push: true
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Builder stage
FROM node:16-alpine AS builder
FROM node:16-bullseye-slim AS builder
WORKDIR /home/node/app

COPY . .
RUN yarn cache clean && yarn --frozen-lockfile && yarn build

# Production stage
FROM node:16-alpine AS production
FROM node:16-bullseye-slim AS production
WORKDIR /home/node/app

COPY --from=builder /home/node/app/package.json .
Expand Down
2 changes: 1 addition & 1 deletion cli/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:16-alpine
FROM node:16-bullseye-slim

WORKDIR /home/node/app

Expand Down
2 changes: 1 addition & 1 deletion development.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:16-alpine
FROM node:16-bullseye-slim
WORKDIR /home/node/app

# Copy package.json and yarn.lock and npmrc to the container
Expand Down
2 changes: 1 addition & 1 deletion samples/wallet-mock/config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module.exports = {
walletBackendUrl: "http://127.0.0.1:8002",
walletBackendUrl: "http://wallet-backend-server:8002",
// trustedIssuerDID: "did:ebsi:zc6MhmU4NbKSAtAHx8XgpEW",
uoaTrustedIssuerDID: "did:ebsi:zpq1XFkNWgsGB6MuvJp21vA",
vidTrustedIssuerDID: "did:ebsi:zyhE5cJ7VVqYT4gZmoKadFt",
Expand Down
2 changes: 1 addition & 1 deletion samples/wallet-mock/development.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:16-alpine
FROM node:16-bullseye-slim
WORKDIR /home/node/app

# Copy package.json and yarn.lock and npmrc to the container
Expand Down
51 changes: 38 additions & 13 deletions src/entities/user.entity.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { Err, Ok, Result } from "ts-results";
import { Entity, PrimaryGeneratedColumn, Column, Repository} from "typeorm"
import AppDataSource from "../AppDataSource";
import crypto from "node:crypto";

import AppDataSource from "../AppDataSource";
import * as scrypt from "../scrypt";


@Entity({ name: "user" })
class UserEntity {
@PrimaryGeneratedColumn()
Expand Down Expand Up @@ -114,18 +118,39 @@ async function getUserByDID(did: string): Promise<Result<UserEntity, GetUserErr>

async function getUserByCredentials(username: string, password: string): Promise<Result<UserEntity, GetUserErr>> {
try {
return await userRepository.manager.transaction(async (manager) => {
const user = await manager.findOne(UserEntity, { where: { username } });
if (user) {
const scryptRes = await scrypt.verifyHash(password, user.passwordHash);
if (scryptRes.ok) {
if (scryptRes.val) {
return Ok(user);
} else {
return Err(GetUserErr.NOT_EXISTS);
}

} else {
// User isn't migrated to scrypt yet - fall back to sha256
const sha256Hash = crypto.createHash('sha256').update(password).digest('base64');

if (user.passwordHash === sha256Hash) {
// Upgrade the user to scrypt
user.passwordHash = await scrypt.createHash(password);
await manager.save(user);

return Ok(user);
} else {
return Err(GetUserErr.NOT_EXISTS);
}
}

const passwordHash = crypto.createHash('sha256').update(password).digest('base64');
const res = await AppDataSource.getRepository(UserEntity)
.createQueryBuilder("user")
.where("user.username = :username and user.passwordHash = :passwordHash", { username: username, passwordHash: passwordHash })
.getOne();
if (!res) {
return Err(GetUserErr.NOT_EXISTS);
}
return Ok(res);
}
catch(e) {
} else {
// Compute a throwaway hash anyway so we don't leak timing information
await scrypt.createHash(password);
return Err(GetUserErr.NOT_EXISTS);
}
});
} catch (e) {
console.log(e);
return Err(GetUserErr.DB_ERR)
}
Expand Down Expand Up @@ -198,4 +223,4 @@ export {
getUserByUsername,
getAllUsers,
storeKeypair
}
}
68 changes: 68 additions & 0 deletions src/scrypt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import crypto from "node:crypto";
import base64url from "base64url";
import { Err, Ok, Result } from "ts-results";


// Settings for new password hashes
// Best practice guidelines from https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#scrypt
const keyLen: number = 64;
const cost: number = 131072; // 2^17
const blockSize: number = 8;
const maxmem: number = 128 * cost * blockSize * 2;


function parseParams(passwordHash: string): Result<{ salt: Buffer, keyLen: number, cost: number, blockSize: number }, void> {
try {
if (!passwordHash.startsWith("$")) {
return Err.EMPTY;
}

const splits = passwordHash.split('$');
const keyLen = parseInt(splits[1], 10);
const cost = parseInt(splits[2], 10);
const blockSize = parseInt(splits[3], 10);
const salt = base64url.toBuffer(splits[4]);
return Ok({ salt, keyLen, cost, blockSize });

} catch (e) {
return Err.EMPTY;
}
}

async function computeScrypt(password: string, salt: Buffer, keyLen: number, cost: number, blockSize: number): Promise<string> {
return new Promise((resolve, reject) => {
crypto.scrypt(
Buffer.from(password, "utf8"),
salt,
keyLen,
{ cost, blockSize, maxmem },
(err, derivedKey) => {
if (err) {
console.error("Failed to compute scrypt hash", err);
reject(err);
} else {
const result = "$" + [keyLen, cost, blockSize, base64url.encode(salt), base64url.encode(derivedKey)].join("$");
resolve(result);
}
},
);
});
}

export async function createHash(password: string): Promise<string> {
return await computeScrypt(password, crypto.randomBytes(32), keyLen, cost, blockSize);
}

/**
* @return Ok(true) if password matches; Ok(false) if password is scrypt-hashed but does not match; Err(void) if password is not scrypt-hashed.
*/
export async function verifyHash(password: string, scryptHash: string): Promise<Result<boolean, void>> {
const decodeRes = parseParams(scryptHash);
if (decodeRes.ok) {
const { salt, keyLen, cost, blockSize } = decodeRes.val;
const encoded = await computeScrypt(password, salt, keyLen, cost, blockSize);
return Ok(encoded === scryptHash);
} else {
return Err.EMPTY;
}
}

0 comments on commit 1d12d26

Please sign in to comment.