Research
Security News
Threat Actor Exposes Playbook for Exploiting npm to Build Blockchain-Powered Botnets
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
fastify-opaque-apake
Advanced tools
Fastify plugin to implement the OPAQUE aPAKE protocol. Uses @squirrelchat/opaque-wasm-server
under the hood, itself using opaque-ke to do the real work.
This plugins depends on @fastify/session
(or any compatible plugin such
as @fastify/secure-session
) to handle state memoization during login.
However, if you wish you can use it witout a session plugin.
The underlying library uses the following OPAQUE configuration, based on the recommendations of the OPAQUE draft:
Make sure to match this configuration in your clients, otherwise the protocol will not be able to execute. For
browser clients, we recommend @squirrelchat/opaque-wasm-client
.
Totally unbiased recommendation, of course :whistle:
[pnpm | yarn | npm] i fastify-opaque-apake
fastify.register(import('@fastify/cookie'), { ... })
fastify.register(import('@fastify/session'), { ... })
fastify.register(import('fastify-opaque-apake'), { ... })
Once registered, you have the OPAQUE server instance accessible via fastify.opaque
. However, you shouldn't need to
use it as more convenient methods are added to the FastifyRequest
object.
These methods will handle temporary state holding for you (by forwarding the work to @fastify/session
, itself capable
of dealing with scaled environments by using a Redis-backed store for example).
The examples below are absolutely NOT production ready. They show off the API of the plugin, but lack error handling.
Every call to *Opaque*
should be wrapped in a try/catch
block, body should be validated (at least make sure it's
an array of numbers, the rest will be handled by the lib)!
fastify.post('/auth/register/init', (request, reply) => {
const reqBytes = new Uint8Array(request.body.request)
const resBytes = request.startOpaqueRegistration(request.body.username, reqBytes)
return { response: Array.from(resBytes) }
})
fastify.post('/auth/register/finalize', (request, reply) => {
const recordBytes = new Uint8Array(request.body.record)
const credentials = request.finishOpaqueRegistration()
// store credentials to database
reply.code(204).send()
})
fastify.post('/auth/login/init', (request, reply) => {
// fetch record from database
const record = ...
// A note on account enumeration:
// The OPAQUE protocol protects against account enumeration
// by design during authentication. To achieve this, you must
// engage in the protocol even if the account does not exists.
// opaque-wasm and the underlying lib does this by using a fake
// random record when no record is specified.
//
// Whether to do this step or not is up to you. If account
// enumeration during authentication is not a concern for you,
// you may skip this and simply send a clear error right now to
// the client.
const reqBytes = new Uint8Array(request.body.request)
const resBytes = request.startOpaqueLogin(request.body.username, reqBytes, record)
return { response: Array.from(resBytes) }
})
fastify.post('/auth/login/finalize', (request, reply) => {
const finishBytes = new Uint8Array(request.body.finish)
const sessionKey = request.finishOpaqueLogin(finishBytes)
reply.code(204).send()
})
The state holds the salt and the keypair used by the server. This keypair must not change, and must be the same across all instances if you have multiple instances of your app. There are 3 ways of providing the state to the plugin: using a static one, using a provider, or pointing to a file.
With a static state, you are responsible for loading/saving the state.
const state = loadState()
fastify.register(import('fastify-opaque-apake'), { state: state })
.after()
.then(() => saveState(fastify.opaque.getState()))
With a provider, the library uses functions you've provided to load/save the state. Your functions can return promises and the library will await them accordingly.
fastify.register(import('fastify-opaque-apake'), {
getState: () => ...,
setState: (state) => { ... },
})
When pointing to a file, the plugin will read/write the file by itself. Please note that the OPAQUE keys are extremely sensitive, and storing them to a file isn't the best for security.
fastify.register(import('fastify-opaque-apake'), { stateFile: './opaque.bin' })
In case you need to handle the OPAQUE state in a specific way, and don't want to register a session plugin for this
reason, you can use fastify-opaque-apake/core
.
fastify.register(import('fastify-opaque-apake/core'), { ... })
When registered like this, you only get the fastify.opaque
decorator. The helpers on FastifyRequest
are not
registered, and you must handle the state management by yourself during login.
FAQs
Fastify plugin to implement the OPAQUE aPAKE protocol
The npm package fastify-opaque-apake receives a total of 0 weekly downloads. As such, fastify-opaque-apake popularity was classified as not popular.
We found that fastify-opaque-apake demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.