1
0
forked from dachan/dach

implemented creation of boards, their listing, admin login and initialization of the database

This commit is contained in:
2023-10-27 18:42:05 +03:00
parent aa72ada0ab
commit 5a1e2a7730
272 changed files with 29607 additions and 7 deletions

186
node_modules/pg/lib/crypto/sasl.js generated vendored Normal file
View File

@@ -0,0 +1,186 @@
'use strict'
const crypto = require('./utils')
function startSession(mechanisms) {
if (mechanisms.indexOf('SCRAM-SHA-256') === -1) {
throw new Error('SASL: Only mechanism SCRAM-SHA-256 is currently supported')
}
const clientNonce = crypto.randomBytes(18).toString('base64')
return {
mechanism: 'SCRAM-SHA-256',
clientNonce,
response: 'n,,n=*,r=' + clientNonce,
message: 'SASLInitialResponse',
}
}
async function continueSession(session, password, serverData) {
if (session.message !== 'SASLInitialResponse') {
throw new Error('SASL: Last message was not SASLInitialResponse')
}
if (typeof password !== 'string') {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string')
}
if (password === '') {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a non-empty string')
}
if (typeof serverData !== 'string') {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: serverData must be a string')
}
const sv = parseServerFirstMessage(serverData)
if (!sv.nonce.startsWith(session.clientNonce)) {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce does not start with client nonce')
} else if (sv.nonce.length === session.clientNonce.length) {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce is too short')
}
var clientFirstMessageBare = 'n=*,r=' + session.clientNonce
var serverFirstMessage = 'r=' + sv.nonce + ',s=' + sv.salt + ',i=' + sv.iteration
var clientFinalMessageWithoutProof = 'c=biws,r=' + sv.nonce
var authMessage = clientFirstMessageBare + ',' + serverFirstMessage + ',' + clientFinalMessageWithoutProof
var saltBytes = Buffer.from(sv.salt, 'base64')
var saltedPassword = await crypto.deriveKey(password, saltBytes, sv.iteration)
var clientKey = await crypto.hmacSha256(saltedPassword, 'Client Key')
var storedKey = await crypto.sha256(clientKey)
var clientSignature = await crypto.hmacSha256(storedKey, authMessage)
var clientProof = xorBuffers(Buffer.from(clientKey), Buffer.from(clientSignature)).toString('base64')
var serverKey = await crypto.hmacSha256(saltedPassword, 'Server Key')
var serverSignatureBytes = await crypto.hmacSha256(serverKey, authMessage)
session.message = 'SASLResponse'
session.serverSignature = Buffer.from(serverSignatureBytes).toString('base64')
session.response = clientFinalMessageWithoutProof + ',p=' + clientProof
}
function finalizeSession(session, serverData) {
if (session.message !== 'SASLResponse') {
throw new Error('SASL: Last message was not SASLResponse')
}
if (typeof serverData !== 'string') {
throw new Error('SASL: SCRAM-SERVER-FINAL-MESSAGE: serverData must be a string')
}
const { serverSignature } = parseServerFinalMessage(serverData)
if (serverSignature !== session.serverSignature) {
throw new Error('SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature does not match')
}
}
/**
* printable = %x21-2B / %x2D-7E
* ;; Printable ASCII except ",".
* ;; Note that any "printable" is also
* ;; a valid "value".
*/
function isPrintableChars(text) {
if (typeof text !== 'string') {
throw new TypeError('SASL: text must be a string')
}
return text
.split('')
.map((_, i) => text.charCodeAt(i))
.every((c) => (c >= 0x21 && c <= 0x2b) || (c >= 0x2d && c <= 0x7e))
}
/**
* base64-char = ALPHA / DIGIT / "/" / "+"
*
* base64-4 = 4base64-char
*
* base64-3 = 3base64-char "="
*
* base64-2 = 2base64-char "=="
*
* base64 = *base64-4 [base64-3 / base64-2]
*/
function isBase64(text) {
return /^(?:[a-zA-Z0-9+/]{4})*(?:[a-zA-Z0-9+/]{2}==|[a-zA-Z0-9+/]{3}=)?$/.test(text)
}
function parseAttributePairs(text) {
if (typeof text !== 'string') {
throw new TypeError('SASL: attribute pairs text must be a string')
}
return new Map(
text.split(',').map((attrValue) => {
if (!/^.=/.test(attrValue)) {
throw new Error('SASL: Invalid attribute pair entry')
}
const name = attrValue[0]
const value = attrValue.substring(2)
return [name, value]
})
)
}
function parseServerFirstMessage(data) {
const attrPairs = parseAttributePairs(data)
const nonce = attrPairs.get('r')
if (!nonce) {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce missing')
} else if (!isPrintableChars(nonce)) {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce must only contain printable characters')
}
const salt = attrPairs.get('s')
if (!salt) {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: salt missing')
} else if (!isBase64(salt)) {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: salt must be base64')
}
const iterationText = attrPairs.get('i')
if (!iterationText) {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration missing')
} else if (!/^[1-9][0-9]*$/.test(iterationText)) {
throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: invalid iteration count')
}
const iteration = parseInt(iterationText, 10)
return {
nonce,
salt,
iteration,
}
}
function parseServerFinalMessage(serverData) {
const attrPairs = parseAttributePairs(serverData)
const serverSignature = attrPairs.get('v')
if (!serverSignature) {
throw new Error('SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature is missing')
} else if (!isBase64(serverSignature)) {
throw new Error('SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature must be base64')
}
return {
serverSignature,
}
}
function xorBuffers(a, b) {
if (!Buffer.isBuffer(a)) {
throw new TypeError('first argument must be a Buffer')
}
if (!Buffer.isBuffer(b)) {
throw new TypeError('second argument must be a Buffer')
}
if (a.length !== b.length) {
throw new Error('Buffer lengths must match')
}
if (a.length === 0) {
throw new Error('Buffers cannot be empty')
}
return Buffer.from(a.map((_, i) => a[i] ^ b[i]))
}
module.exports = {
startSession,
continueSession,
finalizeSession,
}

37
node_modules/pg/lib/crypto/utils-legacy.js generated vendored Normal file
View File

@@ -0,0 +1,37 @@
'use strict'
// This file contains crypto utility functions for versions of Node.js < 15.0.0,
// which does not support the WebCrypto.subtle API.
const nodeCrypto = require('crypto')
function md5(string) {
return nodeCrypto.createHash('md5').update(string, 'utf-8').digest('hex')
}
// See AuthenticationMD5Password at https://www.postgresql.org/docs/current/static/protocol-flow.html
function postgresMd5PasswordHash(user, password, salt) {
var inner = md5(password + user)
var outer = md5(Buffer.concat([Buffer.from(inner), salt]))
return 'md5' + outer
}
function sha256(text) {
return nodeCrypto.createHash('sha256').update(text).digest()
}
function hmacSha256(key, msg) {
return nodeCrypto.createHmac('sha256', key).update(msg).digest()
}
async function deriveKey(password, salt, iterations) {
return nodeCrypto.pbkdf2Sync(password, salt, iterations, 32, 'sha256')
}
module.exports = {
postgresMd5PasswordHash,
randomBytes: nodeCrypto.randomBytes,
deriveKey,
sha256,
hmacSha256,
md5,
}

83
node_modules/pg/lib/crypto/utils-webcrypto.js generated vendored Normal file
View File

@@ -0,0 +1,83 @@
const nodeCrypto = require('crypto')
module.exports = {
postgresMd5PasswordHash,
randomBytes,
deriveKey,
sha256,
hmacSha256,
md5,
}
/**
* The Web Crypto API - grabbed from the Node.js library or the global
* @type Crypto
*/
const webCrypto = nodeCrypto.webcrypto || globalThis.crypto
/**
* The SubtleCrypto API for low level crypto operations.
* @type SubtleCrypto
*/
const subtleCrypto = webCrypto.subtle
const textEncoder = new TextEncoder()
/**
*
* @param {*} length
* @returns
*/
function randomBytes(length) {
return webCrypto.getRandomValues(Buffer.alloc(length))
}
async function md5(string) {
try {
return nodeCrypto.createHash('md5').update(string, 'utf-8').digest('hex')
} catch (e) {
// `createHash()` failed so we are probably not in Node.js, use the WebCrypto API instead.
// Note that the MD5 algorithm on WebCrypto is not available in Node.js.
// This is why we cannot just use WebCrypto in all environments.
const data = typeof string === 'string' ? textEncoder.encode(string) : string
const hash = await subtleCrypto.digest('MD5', data)
return Array.from(new Uint8Array(hash))
.map((b) => b.toString(16).padStart(2, '0'))
.join('')
}
}
// See AuthenticationMD5Password at https://www.postgresql.org/docs/current/static/protocol-flow.html
async function postgresMd5PasswordHash(user, password, salt) {
var inner = await md5(password + user)
var outer = await md5(Buffer.concat([Buffer.from(inner), salt]))
return 'md5' + outer
}
/**
* Create a SHA-256 digest of the given data
* @param {Buffer} data
*/
async function sha256(text) {
return await subtleCrypto.digest('SHA-256', text)
}
/**
* Sign the message with the given key
* @param {ArrayBuffer} keyBuffer
* @param {string} msg
*/
async function hmacSha256(keyBuffer, msg) {
const key = await subtleCrypto.importKey('raw', keyBuffer, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign'])
return await subtleCrypto.sign('HMAC', key, textEncoder.encode(msg))
}
/**
* Derive a key from the password and salt
* @param {string} password
* @param {Uint8Array} salt
* @param {number} iterations
*/
async function deriveKey(password, salt, iterations) {
const key = await subtleCrypto.importKey('raw', textEncoder.encode(password), 'PBKDF2', false, ['deriveBits'])
const params = { name: 'PBKDF2', hash: 'SHA-256', salt: salt, iterations: iterations }
return await subtleCrypto.deriveBits(params, key, 32 * 8, ['deriveBits'])
}

9
node_modules/pg/lib/crypto/utils.js generated vendored Normal file
View File

@@ -0,0 +1,9 @@
'use strict'
const useLegacyCrypto = parseInt(process.versions && process.versions.node && process.versions.node.split('.')[0]) < 15
if (useLegacyCrypto) {
// We are on an old version of Node.js that requires legacy crypto utilities.
module.exports = require('./utils-legacy')
} else {
module.exports = require('./utils-webcrypto');
}