.
This commit is contained in:
		
							
								
								
									
										122
									
								
								qwen/nodejs/node_modules/pg/lib/crypto/cert-signatures.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								qwen/nodejs/node_modules/pg/lib/crypto/cert-signatures.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,122 @@
 | 
			
		||||
function x509Error(msg, cert) {
 | 
			
		||||
  return new Error('SASL channel binding: ' + msg + ' when parsing public certificate ' + cert.toString('base64'))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function readASN1Length(data, index) {
 | 
			
		||||
  let length = data[index++]
 | 
			
		||||
  if (length < 0x80) return { length, index }
 | 
			
		||||
 | 
			
		||||
  const lengthBytes = length & 0x7f
 | 
			
		||||
  if (lengthBytes > 4) throw x509Error('bad length', data)
 | 
			
		||||
 | 
			
		||||
  length = 0
 | 
			
		||||
  for (let i = 0; i < lengthBytes; i++) {
 | 
			
		||||
    length = (length << 8) | data[index++]
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return { length, index }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function readASN1OID(data, index) {
 | 
			
		||||
  if (data[index++] !== 0x6) throw x509Error('non-OID data', data) // 6 = OID
 | 
			
		||||
 | 
			
		||||
  const { length: OIDLength, index: indexAfterOIDLength } = readASN1Length(data, index)
 | 
			
		||||
  index = indexAfterOIDLength
 | 
			
		||||
  const lastIndex = index + OIDLength
 | 
			
		||||
 | 
			
		||||
  const byte1 = data[index++]
 | 
			
		||||
  let oid = ((byte1 / 40) >> 0) + '.' + (byte1 % 40)
 | 
			
		||||
 | 
			
		||||
  while (index < lastIndex) {
 | 
			
		||||
    // loop over numbers in OID
 | 
			
		||||
    let value = 0
 | 
			
		||||
    while (index < lastIndex) {
 | 
			
		||||
      // loop over bytes in number
 | 
			
		||||
      const nextByte = data[index++]
 | 
			
		||||
      value = (value << 7) | (nextByte & 0x7f)
 | 
			
		||||
      if (nextByte < 0x80) break
 | 
			
		||||
    }
 | 
			
		||||
    oid += '.' + value
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return { oid, index }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function expectASN1Seq(data, index) {
 | 
			
		||||
  if (data[index++] !== 0x30) throw x509Error('non-sequence data', data) // 30 = Sequence
 | 
			
		||||
  return readASN1Length(data, index)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function signatureAlgorithmHashFromCertificate(data, index) {
 | 
			
		||||
  // read this thread: https://www.postgresql.org/message-id/17760-b6c61e752ec07060%40postgresql.org
 | 
			
		||||
  if (index === undefined) index = 0
 | 
			
		||||
  index = expectASN1Seq(data, index).index
 | 
			
		||||
  const { length: certInfoLength, index: indexAfterCertInfoLength } = expectASN1Seq(data, index)
 | 
			
		||||
  index = indexAfterCertInfoLength + certInfoLength // skip over certificate info
 | 
			
		||||
  index = expectASN1Seq(data, index).index // skip over signature length field
 | 
			
		||||
  const { oid, index: indexAfterOID } = readASN1OID(data, index)
 | 
			
		||||
  switch (oid) {
 | 
			
		||||
    // RSA
 | 
			
		||||
    case '1.2.840.113549.1.1.4':
 | 
			
		||||
      return 'MD5'
 | 
			
		||||
    case '1.2.840.113549.1.1.5':
 | 
			
		||||
      return 'SHA-1'
 | 
			
		||||
    case '1.2.840.113549.1.1.11':
 | 
			
		||||
      return 'SHA-256'
 | 
			
		||||
    case '1.2.840.113549.1.1.12':
 | 
			
		||||
      return 'SHA-384'
 | 
			
		||||
    case '1.2.840.113549.1.1.13':
 | 
			
		||||
      return 'SHA-512'
 | 
			
		||||
    case '1.2.840.113549.1.1.14':
 | 
			
		||||
      return 'SHA-224'
 | 
			
		||||
    case '1.2.840.113549.1.1.15':
 | 
			
		||||
      return 'SHA512-224'
 | 
			
		||||
    case '1.2.840.113549.1.1.16':
 | 
			
		||||
      return 'SHA512-256'
 | 
			
		||||
    // ECDSA
 | 
			
		||||
    case '1.2.840.10045.4.1':
 | 
			
		||||
      return 'SHA-1'
 | 
			
		||||
    case '1.2.840.10045.4.3.1':
 | 
			
		||||
      return 'SHA-224'
 | 
			
		||||
    case '1.2.840.10045.4.3.2':
 | 
			
		||||
      return 'SHA-256'
 | 
			
		||||
    case '1.2.840.10045.4.3.3':
 | 
			
		||||
      return 'SHA-384'
 | 
			
		||||
    case '1.2.840.10045.4.3.4':
 | 
			
		||||
      return 'SHA-512'
 | 
			
		||||
    // RSASSA-PSS: hash is indicated separately
 | 
			
		||||
    case '1.2.840.113549.1.1.10': {
 | 
			
		||||
      index = indexAfterOID
 | 
			
		||||
      index = expectASN1Seq(data, index).index
 | 
			
		||||
      if (data[index++] !== 0xa0) throw x509Error('non-tag data', data) // a0 = constructed tag 0
 | 
			
		||||
      index = readASN1Length(data, index).index // skip over tag length field
 | 
			
		||||
      index = expectASN1Seq(data, index).index // skip over sequence length field
 | 
			
		||||
      const { oid: hashOID } = readASN1OID(data, index)
 | 
			
		||||
      switch (hashOID) {
 | 
			
		||||
        // standalone hash OIDs
 | 
			
		||||
        case '1.2.840.113549.2.5':
 | 
			
		||||
          return 'MD5'
 | 
			
		||||
        case '1.3.14.3.2.26':
 | 
			
		||||
          return 'SHA-1'
 | 
			
		||||
        case '2.16.840.1.101.3.4.2.1':
 | 
			
		||||
          return 'SHA-256'
 | 
			
		||||
        case '2.16.840.1.101.3.4.2.2':
 | 
			
		||||
          return 'SHA-384'
 | 
			
		||||
        case '2.16.840.1.101.3.4.2.3':
 | 
			
		||||
          return 'SHA-512'
 | 
			
		||||
      }
 | 
			
		||||
      throw x509Error('unknown hash OID ' + hashOID, data)
 | 
			
		||||
    }
 | 
			
		||||
    // Ed25519 -- see https: return//github.com/openssl/openssl/issues/15477
 | 
			
		||||
    case '1.3.101.110':
 | 
			
		||||
    case '1.3.101.112': // ph
 | 
			
		||||
      return 'SHA-512'
 | 
			
		||||
    // Ed448 -- still not in pg 17.2 (if supported, digest would be SHAKE256 x 64 bytes)
 | 
			
		||||
    case '1.3.101.111':
 | 
			
		||||
    case '1.3.101.113': // ph
 | 
			
		||||
      throw x509Error('Ed448 certificate channel binding is not currently supported by Postgres')
 | 
			
		||||
  }
 | 
			
		||||
  throw x509Error('unknown OID ' + oid, data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = { signatureAlgorithmHashFromCertificate }
 | 
			
		||||
							
								
								
									
										212
									
								
								qwen/nodejs/node_modules/pg/lib/crypto/sasl.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										212
									
								
								qwen/nodejs/node_modules/pg/lib/crypto/sasl.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,212 @@
 | 
			
		||||
'use strict'
 | 
			
		||||
const crypto = require('./utils')
 | 
			
		||||
const { signatureAlgorithmHashFromCertificate } = require('./cert-signatures')
 | 
			
		||||
 | 
			
		||||
function startSession(mechanisms, stream) {
 | 
			
		||||
  const candidates = ['SCRAM-SHA-256']
 | 
			
		||||
  if (stream) candidates.unshift('SCRAM-SHA-256-PLUS') // higher-priority, so placed first
 | 
			
		||||
 | 
			
		||||
  const mechanism = candidates.find((candidate) => mechanisms.includes(candidate))
 | 
			
		||||
 | 
			
		||||
  if (!mechanism) {
 | 
			
		||||
    throw new Error('SASL: Only mechanism(s) ' + candidates.join(' and ') + ' are supported')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (mechanism === 'SCRAM-SHA-256-PLUS' && typeof stream.getPeerCertificate !== 'function') {
 | 
			
		||||
    // this should never happen if we are really talking to a Postgres server
 | 
			
		||||
    throw new Error('SASL: Mechanism SCRAM-SHA-256-PLUS requires a certificate')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const clientNonce = crypto.randomBytes(18).toString('base64')
 | 
			
		||||
  const gs2Header = mechanism === 'SCRAM-SHA-256-PLUS' ? 'p=tls-server-end-point' : stream ? 'y' : 'n'
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    mechanism,
 | 
			
		||||
    clientNonce,
 | 
			
		||||
    response: gs2Header + ',,n=*,r=' + clientNonce,
 | 
			
		||||
    message: 'SASLInitialResponse',
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function continueSession(session, password, serverData, stream) {
 | 
			
		||||
  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')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const clientFirstMessageBare = 'n=*,r=' + session.clientNonce
 | 
			
		||||
  const serverFirstMessage = 'r=' + sv.nonce + ',s=' + sv.salt + ',i=' + sv.iteration
 | 
			
		||||
 | 
			
		||||
  // without channel binding:
 | 
			
		||||
  let channelBinding = stream ? 'eSws' : 'biws' // 'y,,' or 'n,,', base64-encoded
 | 
			
		||||
 | 
			
		||||
  // override if channel binding is in use:
 | 
			
		||||
  if (session.mechanism === 'SCRAM-SHA-256-PLUS') {
 | 
			
		||||
    const peerCert = stream.getPeerCertificate().raw
 | 
			
		||||
    let hashName = signatureAlgorithmHashFromCertificate(peerCert)
 | 
			
		||||
    if (hashName === 'MD5' || hashName === 'SHA-1') hashName = 'SHA-256'
 | 
			
		||||
    const certHash = await crypto.hashByName(hashName, peerCert)
 | 
			
		||||
    const bindingData = Buffer.concat([Buffer.from('p=tls-server-end-point,,'), Buffer.from(certHash)])
 | 
			
		||||
    channelBinding = bindingData.toString('base64')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const clientFinalMessageWithoutProof = 'c=' + channelBinding + ',r=' + sv.nonce
 | 
			
		||||
  const authMessage = clientFirstMessageBare + ',' + serverFirstMessage + ',' + clientFinalMessageWithoutProof
 | 
			
		||||
 | 
			
		||||
  const saltBytes = Buffer.from(sv.salt, 'base64')
 | 
			
		||||
  const saltedPassword = await crypto.deriveKey(password, saltBytes, sv.iteration)
 | 
			
		||||
  const clientKey = await crypto.hmacSha256(saltedPassword, 'Client Key')
 | 
			
		||||
  const storedKey = await crypto.sha256(clientKey)
 | 
			
		||||
  const clientSignature = await crypto.hmacSha256(storedKey, authMessage)
 | 
			
		||||
  const clientProof = xorBuffers(Buffer.from(clientKey), Buffer.from(clientSignature)).toString('base64')
 | 
			
		||||
  const serverKey = await crypto.hmacSha256(saltedPassword, 'Server Key')
 | 
			
		||||
  const 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,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										43
									
								
								qwen/nodejs/node_modules/pg/lib/crypto/utils-legacy.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								qwen/nodejs/node_modules/pg/lib/crypto/utils-legacy.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
'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) {
 | 
			
		||||
  const inner = md5(password + user)
 | 
			
		||||
  const outer = md5(Buffer.concat([Buffer.from(inner), salt]))
 | 
			
		||||
  return 'md5' + outer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function sha256(text) {
 | 
			
		||||
  return nodeCrypto.createHash('sha256').update(text).digest()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function hashByName(hashName, text) {
 | 
			
		||||
  hashName = hashName.replace(/(\D)-/, '$1') // e.g. SHA-256 -> SHA256
 | 
			
		||||
  return nodeCrypto.createHash(hashName).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,
 | 
			
		||||
  hashByName,
 | 
			
		||||
  hmacSha256,
 | 
			
		||||
  md5,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										89
									
								
								qwen/nodejs/node_modules/pg/lib/crypto/utils-webcrypto.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								qwen/nodejs/node_modules/pg/lib/crypto/utils-webcrypto.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,89 @@
 | 
			
		||||
const nodeCrypto = require('crypto')
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  postgresMd5PasswordHash,
 | 
			
		||||
  randomBytes,
 | 
			
		||||
  deriveKey,
 | 
			
		||||
  sha256,
 | 
			
		||||
  hashByName,
 | 
			
		||||
  hmacSha256,
 | 
			
		||||
  md5,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The Web Crypto API - grabbed from the Node.js library or the global
 | 
			
		||||
 * @type Crypto
 | 
			
		||||
 */
 | 
			
		||||
// eslint-disable-next-line no-undef
 | 
			
		||||
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) {
 | 
			
		||||
  const inner = await md5(password + user)
 | 
			
		||||
  const 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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function hashByName(hashName, text) {
 | 
			
		||||
  return await subtleCrypto.digest(hashName, 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
									
								
								qwen/nodejs/node_modules/pg/lib/crypto/utils.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								qwen/nodejs/node_modules/pg/lib/crypto/utils.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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')
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user