mirror of https://codeberg.org/pzp/pzp-keypair.git
93 lines
2.5 KiB
JavaScript
93 lines
2.5 KiB
JavaScript
// @ts-ignore
|
|
const sodium = require('sodium-universal')
|
|
const b4a = require('b4a')
|
|
const base58 = require('bs58')
|
|
const { getCurve, generate } = require('./curves')
|
|
const StorageClass =
|
|
typeof window !== 'undefined'
|
|
? require('./storage/browser')
|
|
: require('./storage/node')
|
|
|
|
/**
|
|
* @typedef {import('./curves').Keypair} Keypair
|
|
* @typedef {import('./curves').KeypairPublicSlice} KeypairPublicSlice
|
|
* @typedef {import('./curves').KeypairPrivateSlice} KeypairPrivateSlice
|
|
* @typedef {import('./curves').CurveName} CurveName
|
|
*
|
|
* @typedef {Buffer | Uint8Array} B4A
|
|
*/
|
|
|
|
/**
|
|
* @param {any} x
|
|
* @returns {x is string}
|
|
*/
|
|
function isString(x) {
|
|
return typeof x === 'string'
|
|
}
|
|
|
|
/**
|
|
* @param {B4A} input
|
|
* @param {string | B4A} key
|
|
* @returns {B4A}
|
|
*/
|
|
function hmac(input, key) {
|
|
if (isString(key)) key = b4a.from(base58.decode(key))
|
|
const output = b4a.alloc(sodium.crypto_auth_BYTES)
|
|
sodium.crypto_auth(output, input, key)
|
|
return output
|
|
}
|
|
|
|
/**
|
|
* Takes a keypair object (where `.public` is allowed to be undefined), a
|
|
* message as a Buffer (and an optional hmacKey) and returns a signature of
|
|
* the given message. The signature is string encoded in base58.
|
|
*
|
|
* @param {KeypairPrivateSlice} keypair
|
|
* @param {B4A} msg
|
|
* @param {(B4A | string)=} hmacKey
|
|
* @returns {string}
|
|
*/
|
|
function sign(keypair, msg, hmacKey) {
|
|
if (!b4a.isBuffer(msg)) throw new Error('Signable message should be Buffer')
|
|
const curve = getCurve(keypair.curve)
|
|
|
|
if (hmacKey) msg = hmac(msg, hmacKey)
|
|
|
|
return curve.sign(keypair, msg)
|
|
}
|
|
|
|
/**
|
|
* Takes a keypair object (where `private` is allowed to be undefined), a
|
|
* message Buffer and its signature string (and an optional hmacKey), and
|
|
* returns true if the signature is valid for the message, false otherwise.
|
|
*
|
|
* @param {KeypairPublicSlice} keypair
|
|
* @param {B4A} msg
|
|
* @param {string} sig
|
|
* @param {(B4A | string)=} hmacKey
|
|
* @returns {boolean}
|
|
*/
|
|
function verify(keypair, msg, sig, hmacKey) {
|
|
if (!isString(sig)) throw new Error('sig should be string')
|
|
if (!b4a.isBuffer(msg)) throw new Error('Signed message should be Buffer')
|
|
const curve = getCurve(keypair.curve)
|
|
|
|
if (hmacKey) msg = hmac(msg, hmacKey)
|
|
|
|
return curve.verify(keypair, sig, msg)
|
|
}
|
|
|
|
const storage = new StorageClass()
|
|
|
|
module.exports = {
|
|
generate,
|
|
sign,
|
|
verify,
|
|
create: storage.create.bind(storage),
|
|
load: storage.load.bind(storage),
|
|
createSync: storage.createSync.bind(storage),
|
|
loadSync: storage.loadSync.bind(storage),
|
|
loadOrCreate: storage.loadOrCreate.bind(storage),
|
|
loadOrCreateSync: storage.loadOrCreateSync.bind(storage),
|
|
}
|