return Promise.resolve().then(() => { // must be bip39 mnemonic if (!bip39.validateMnemonic(phrase)) { throw new Error('Not a valid bip39 nmemonic') } // normalize plaintext to fixed length byte string const plaintextNormalized = Buffer.from( bip39.mnemonicToEntropy(phrase), 'hex' ) // AES-128-CBC with SHA256 HMAC const salt = crypto.randomBytes(16) const keysAndIV = crypto.pbkdf2Sync(password, salt, 100000, 48, 'sha512') const encKey = keysAndIV.slice(0, 16) const macKey = keysAndIV.slice(16, 32) const iv = keysAndIV.slice(32, 48) const cipher = crypto.createCipheriv('aes-128-cbc', encKey, iv) let cipherText = cipher.update(plaintextNormalized).toString('hex') cipherText += cipher.final().toString('hex') const hmacPayload = Buffer.concat([salt, Buffer.from(cipherText, 'hex')]) const hmac = crypto.createHmac('sha256', macKey) hmac.write(hmacPayload) const hmacDigest = hmac.digest() const payload = Buffer.concat([salt, hmacDigest, Buffer.from(cipherText, 'hex')]) return payload })
UserSchema.methods.hashPassword = function(password) { if (this.salt && password) { return crypto.pbkdf2Sync(password, this.salt, 10000, 64).toString("base64"); } else { return password; } };
export function HashSync(data: string, salt?: string) { if (typeof salt === 'undefined' || !salt) { salt = GenSalt(); } const key = crypto.pbkdf2Sync(data, salt, 150000, HASHLENGHT, 'sha512').toString('hex'); return salt + key; }
export function makeHash(decryptedPassword:string, salt?:string):hashResult { if (!salt) { salt = crypto.randomBytes(16).toString('base64') } const saltBuf = new Buffer(salt, 'base64') const hashedPassword = crypto.pbkdf2Sync(`${LOCAL_AUTH_SALT}${decryptedPassword}`, saltBuf, 10000, 512, 'sha512') return { hashedPassword: hashedPassword.toString(), salt: salt } }
private encryptPassword(password: string, salt: string): string{ if (!password || !salt) { return null; } let defaultIterations = 10000; let defaultKeyLength = 64; let base64Salt = new Buffer(salt, 'base64'); return crypto.pbkdf2Sync(password, base64Salt, defaultIterations, defaultKeyLength, 'sha512') .toString('base64'); }
export function hashPassword(plaintext: string, salt: string, options: IPasswordOptions): string { assert.ok(salt.length === options.saltLength, 'incompatible salt length') return crypto .pbkdf2Sync( plaintext, salt + options.secret, options.iterations, options.hashedPasswordLength / 2, options.algorithm, ) .toString('hex') }
return Promise.resolve().then(() => { const salt = dataBuffer.slice(0, 16) const hmacSig = dataBuffer.slice(16, 48) // 32 bytes const cipherText = dataBuffer.slice(48) const hmacPayload = Buffer.concat([salt, cipherText]) const keysAndIV = crypto.pbkdf2Sync(password, salt, 100000, 48, 'sha512') const encKey = keysAndIV.slice(0, 16) const macKey = keysAndIV.slice(16, 32) const iv = keysAndIV.slice(32, 48) const decipher = crypto.createDecipheriv('aes-128-cbc', encKey, iv) let plaintext = decipher.update(cipherText).toString('hex') plaintext += decipher.final().toString('hex') const hmac = crypto.createHmac('sha256', macKey) hmac.write(hmacPayload) const hmacDigest = hmac.digest() // hash both hmacSig and hmacDigest so string comparison time // is uncorrelated to the ciphertext const hmacSigHash = crypto.createHash('sha256') .update(hmacSig) .digest() .toString('hex') const hmacDigestHash = crypto.createHash('sha256') .update(hmacDigest) .digest() .toString('hex') if (hmacSigHash !== hmacDigestHash) { // not authentic throw new PasswordError('Wrong password (HMAC mismatch)') } const mnemonic = bip39.entropyToMnemonic(plaintext) if (!bip39.validateMnemonic(mnemonic)) { throw new PasswordError('Wrong password (invalid plaintext)') } return mnemonic })
export const grades = functions.pubsub.topic('grades').onPublish(event => { const { chicagoId, record } = event.data.json; const basis = [record['term'], record['course'], record['section']].join(); const key = crypto .pbkdf2Sync(basis, chicagoId, 2000000, 20, 'sha512') .toString('base64') .replace(/=/g, '') .replace(/\+/g, '-') .replace(/\//g, '_'); return admin .firestore() .collection('institutions') .doc('uchicago') .collection('grades') .doc(key) .set({ course: record['course'], section: record['section'], term: record['term'], gpa: record['gpa'], tenure: record['tenure'], }); });
*/ encryptPassword(password, callback): any { if (!password || !this.salt) { if (!callback) { return null; } else { return callback('Missing password or salt'); } } let defaultIterations = 10000; let defaultKeyLength = 64; let salt = new Buffer(this.salt, 'base64'); if (!callback) { return crypto.pbkdf2Sync(password, salt, defaultIterations, defaultKeyLength, 'sha512') .toString('base64'); } return crypto.pbkdf2(password, salt, defaultIterations, defaultKeyLength, 'sha512', (err, key) => { if (err) { callback(err); } else { callback(null, key.toString('base64')); } }); } } }); export default User;
encryptPassword: function (password) { if (!password || !this.salt) { return ''; } var salt = new Buffer(this.salt, 'base64'); return crypto.pbkdf2Sync(password, salt, 10000, 64).toString('base64'); }