Skip to content

Commit

Permalink
Remove early return for non commonjs environments (#3033)
Browse files Browse the repository at this point in the history
  • Loading branch information
benjreinhart authored Jul 19, 2023
1 parent 970804b commit 3644730
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 85 deletions.
83 changes: 83 additions & 0 deletions packages/pg/lib/crypto/utils-webcrypto.js
Original file line number Diff line number Diff line change
@@ -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'])
}
87 changes: 2 additions & 85 deletions packages/pg/lib/crypto/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,89 +4,6 @@ const useLegacyCrypto = parseInt(process.versions && process.versions.node && pr
if (useLegacyCrypto) {
// We are on an old version of Node.js that requires legacy crypto utilities.
module.exports = require('./utils-legacy')
return
}

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'])
} else {
module.exports = require('./utils-webcrypto');
}

0 comments on commit 3644730

Please sign in to comment.