module.exports = StringUtils var crypto = require('crypto') var uuid = require('node-uuid') var constants = require('./constants') var bignum = require('bignum') var ursa = require('ursa') var NodeRSA = require('node-rsa') var BufferUtils = require('./buffer-utils') /** * @namespace * @static */ function StringUtils () { // static class } /** * @return {string} milliseconds for current time from epoch as a string */ StringUtils.timestamp = function () { return StringUtils.timestampFrom(new Date()) } /** * @param {Date} date * @return {string} milliseconds date is from epoch as a string */ StringUtils.timestampFrom = function (date) { return '' + date.getTime() } /** * @param {string} str * @param {string} key * @return {string} */ StringUtils.hashHMacToBase64 = function (str, key) { return crypto.createHmac('sha256', key).update(str).digest('base64') } /** * @param {string} str * @return {string} */ StringUtils.md5HashToHex = function (str) { return crypto.createHash('md5').update(str).digest('hex') } /** * @param {string} str * @return {string} */ StringUtils.sha256HashToBase64 = function (str) { return crypto.createHash('sha256').update(str).digest('base64') } /** * @param {string} str * @return {string} */ StringUtils.sha256HashToHex = function (str) { return crypto.createHash('sha256').update(str).digest('hex') } /** * @param {string} first * @param {string} second * @return {string} */ StringUtils.hashSCString = function (first, second) { return BufferUtils.hashSC(new Buffer(first), new Buffer(second)) } /** * Returns the pre-hash string used for Snapchat requests. * * @param {string} username * @param {string} password * @param {string} timestamp * @param {string} endpoint * @return {string} */ StringUtils.getSCPreHashString = function (username, password, timestamp, endpoint) { return username + '|' + password + '|' + timestamp + '|' + endpoint } /** * Attempts to parse the given string as JSON, returning null upon parse error. * * @param {string} input * @return {Object} */ StringUtils.tryParseJSON = function (input) { try { return JSON.parse(input) } catch (e) { return null } } StringUtils.matchGroup = function (input, regex, index) { if (input && typeof input === 'string') { var matches = input.match(regex) if (matches && index < matches.length) { return matches[index] } } return null } /** * @param {string} first * @param {string} second * @return {string} */ StringUtils.SCIdentifier = function (first, second) { return first + '~' + second } /** * @param {string} sender * @return {string} */ StringUtils.mediaIdentifier = function (sender) { var hash = StringUtils.md5HashToHex(uuid.v4()) return sender.toUpperCase() + '~' + hash } /** * @return {string} */ StringUtils.uniqueIdentifer = function () { var hash = StringUtils.md5HashToHex(uuid.v4()) return hash.substr(0, 8) + '-' + hash.substr(8, 4) + '-' + hash.substr(12, 4) + '-' + hash.substr(16, 4) + '-' + hash.substr(20, 12) } /** * Encrypts the given password for use with Google's Android authentication. * * @param {string} gmailEmail * @param {string} gmailPassword * @return {string} */ StringUtils.encryptGmailPassword = function (gmailEmail, gmailPassword) { var keyBuffer = new Buffer(constants.core.googleDefaultPublicKey, 'base64') var halfString1 = keyBuffer.toString('hex').substr(8, 256) var modulus = bignum(halfString1, 16) var halfString2 = keyBuffer.toString('hex').substr(272, 6) var exponent = bignum(halfString2, 16) var shasum = crypto.createHash('sha1') shasum.update(keyBuffer.toString('binary')) var signature = '00' + shasum.digest('hex').substr(0, 8) var pem = ursa .createPublicKeyFromComponents(modulus.toBuffer(), exponent.toBuffer()) .toPublicPem() .toString() var plain = gmailEmail + '\x00' + gmailPassword var key = new NodeRSA(pem) var encrypted = key.encrypt(plain, 'hex') var output = new Buffer(signature + encrypted.toString('hex'), 'hex') var base64Output = output.toString('base64') base64Output = base64Output.replace(/\+/g, '-') base64Output = base64Output.replace(/\//g, '_') return base64Output }