"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.exportCertBinary = exportCertBinary; exports.exportCertBase64 = exportCertBase64; exports.exportPrivateKey = exportPrivateKey; exports.logKeystoreHashes = logKeystoreHashes; exports.logKeystoreCredentials = logKeystoreCredentials; exports.createKeystore = createKeystore; exports.generateUploadKeystore = generateUploadKeystore; function _path() { const data = _interopRequireDefault(require("path")); _path = function () { return data; }; return data; } function _fsExtra() { const data = _interopRequireDefault(require("fs-extra")); _fsExtra = function () { return data; }; return data; } function _chalk() { const data = _interopRequireDefault(require("chalk")); _chalk = function () { return data; }; return data; } function _crypto() { const data = _interopRequireDefault(require("crypto")); _crypto = function () { return data; }; return data; } function _v() { const data = _interopRequireDefault(require("uuid/v4")); _v = function () { return data; }; return data; } function _spawnAsync() { const data = _interopRequireDefault(require("@expo/spawn-async")); _spawnAsync = function () { return data; }; return data; } function _axios() { const data = _interopRequireDefault(require("axios")); _axios = function () { return data; }; return data; } function _progress() { const data = _interopRequireDefault(require("progress")); _progress = function () { return data; }; return data; } function _Logger() { const data = _interopRequireDefault(require("../Logger")); _Logger = function () { return data; }; return data; } function _UserSettings() { const data = _interopRequireDefault(require("../UserSettings")); _UserSettings = function () { return data; }; return data; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const log = _Logger().default.global; const NEWLINE = process.platform === 'win32' ? '\r\n' : '\n'; const javaExecutable = process.platform === 'win32' ? 'java.exe' : 'java'; async function exportCertBinary({ keystorePath, keystorePassword, keyAlias }, certFile) { try { return (0, _spawnAsync().default)('keytool', ['-exportcert', '-keystore', keystorePath, '-storepass', keystorePassword, '-alias', keyAlias, '-file', certFile, '-noprompt', '-storetype', 'JKS']); } catch (err) { if (err.code === 'ENOENT') { log.warn('Are you sure you have keytool installed?'); log.info('keytool is a part of OpenJDK: https://openjdk.java.net/'); log.info('Also make sure that keytool is in your PATH after installation.'); } throw err; } } async function exportCertBase64({ keystorePath, keystorePassword, keyAlias }, certFile) { try { return (0, _spawnAsync().default)('keytool', ['-export', '-rfc', '-keystore', keystorePath, '-storepass', keystorePassword, '-alias', keyAlias, '-file', certFile, '-noprompt', '-storetype', 'JKS']); } catch (err) { if (err.code === 'ENOENT') { log.warn('Are you sure you have keytool installed?'); log.info('keytool is a part of OpenJDK: https://openjdk.java.net/'); log.info('Also make sure that keytool is in your PATH after installation.'); } throw err; } } async function exportPrivateKey({ keystorePath, keystorePassword, keyAlias, keyPassword }, encryptionKey, outputPath) { let nodePty; const ptyTmpDir = '/tmp/pty-tmp-install'; try { // it's not very pretty solution, but we decided to use it because it's affecting only people using // this command and if node-pty is supported on that system instalation process will be invisble for user. nodePty = require('node-pty-prebuilt'); } catch (err) { try { log.info('Installing node-pty-prebuilt in a temporary directory'); await _fsExtra().default.mkdirp(ptyTmpDir); await (0, _spawnAsync().default)('npm', ['init', '--yes'], { cwd: ptyTmpDir }); await (0, _spawnAsync().default)('npm', ['install', 'node-pty-prebuilt'], { cwd: ptyTmpDir, stdio: ['pipe', 1, 2] }); nodePty = require(`${ptyTmpDir}/node_modules/node-pty-prebuilt`); } catch (err) { log.info(`Run ${_chalk().default.cyan('npm -g install node-pty-prebuilt')} to install node pty`); throw new Error('Package node-pty-prebuilt is required to use PEPK tool'); } } const ptySpawn = nodePty.spawn; const encryptToolPath = _path().default.join(_UserSettings().default.dotExpoHomeDirectory(), 'android_tools_pepk.jar'); if (!_fsExtra().default.existsSync(encryptToolPath)) { log.info(`Downloading PEPK tool from Google Play to ${encryptToolPath}`); const downloadUrl = 'https://www.gstatic.com/play-apps-publisher-rapid/signing-tool/prod/pepk.jar'; const file = _fsExtra().default.createWriteStream(encryptToolPath); const response = await (0, _axios().default)({ url: downloadUrl, method: 'GET', responseType: 'stream' }); const bar = new (_progress().default)(' downloading pepk tool [:bar] :rate/bps :percent :etas', { complete: '=', incomplete: ' ', width: 40, total: parseInt(response.headers['content-length'], 10) }); response.data.pipe(file); response.data.on('data', chunk => bar.tick(chunk.length)); await new Promise((resolve, reject) => { file.on('finish', resolve); file.on('error', reject); }); } try { await new Promise((res, rej) => { const child = ptySpawn(javaExecutable, ['-jar', encryptToolPath, '--keystore', keystorePath, '--alias', keyAlias, '--output', outputPath, '--encryptionkey', encryptionKey], { name: 'pepk tool', cols: 80, rows: 30, cwd: process.cwd(), env: process.env }); child.on('error', err => { log.error('error', err); rej(err); }); child.on('exit', exitCode => { if (exitCode !== 0) { rej(exitCode); } else { res(); } }); child.write(keystorePassword + NEWLINE); child.write(keyPassword + NEWLINE); }); log.info(`Exported and encrypted private App Signing Key to file ${outputPath}`); } catch (error) { throw new Error(`PEPK tool failed with return code ${error}`); } finally { _fsExtra().default.remove(ptyTmpDir); } } async function logKeystoreHashes(keystoreInfo, linePrefix = '') { const { keystorePath, keystorePassword, keyAlias } = keystoreInfo; const certFile = `${keystorePath}.cer`; try { await exportCertBinary(keystoreInfo, certFile); const data = await _fsExtra().default.readFile(certFile); const googleHash = _crypto().default.createHash('sha1').update(data).digest('hex').toUpperCase(); const googleHash256 = _crypto().default.createHash('sha256').update(data).digest('hex').toUpperCase(); const fbHash = _crypto().default.createHash('sha1').update(data).digest('base64'); log.info(`${linePrefix}Google Certificate Fingerprint: ${googleHash.replace(/(.{2}(?!$))/g, '$1:')}`); log.info(`${linePrefix}Google Certificate Hash (SHA-1): ${googleHash}`); log.info(`${linePrefix}Google Certificate Hash (SHA-256): ${googleHash256}`); log.info(`${linePrefix}Facebook Key Hash: ${fbHash}`); } catch (err) { if (err.code === 'ENOENT') { log.warn('Are you sure you have keytool installed?'); log.info('keytool is a part of OpenJDK: https://openjdk.java.net/'); log.info('Also make sure that keytool is in your PATH after installation.'); } if (err.stdout) { log.info(err.stdout); } if (err.stderr) { log.error(err.stderr); } throw err; } finally { try { await _fsExtra().default.unlink(certFile); } catch (err) { if (err.code !== 'ENOENT') { log.error(err); } } } } function logKeystoreCredentials({ keystorePassword, keyAlias, keyPassword }, title = 'Keystore credentials', linePrefix = '') { log.info(`${linePrefix}${title} ${linePrefix} Keystore password: ${_chalk().default.bold(keystorePassword)} ${linePrefix} Key alias: ${_chalk().default.bold(keyAlias)} ${linePrefix} Key password: ${_chalk().default.bold(keyPassword)} `); } async function createKeystore({ keystorePath, keystorePassword, keyAlias, keyPassword }, androidPackage) { try { return await (0, _spawnAsync().default)('keytool', ['-genkey', '-v', '-storetype', 'JKS', '-storepass', keystorePassword, '-keypass', keyPassword, '-keystore', keystorePath, '-alias', keyAlias, '-keyalg', 'RSA', '-keysize', '2048', '-validity', '10000', '-dname', `CN=${androidPackage},OU=,O=,L=,S=,C=US`]); } catch (error) { if (error.code === 'ENOENT') { log.warn('Are you sure you have keytool installed?'); log.info('keytool is a part of OpenJDK: https://openjdk.java.net/'); log.info('Also make sure that keytool is in your PATH after installation.'); } throw error; } } async function generateUploadKeystore(uploadKeystorePath, androidPackage, experienceName) { const keystoreData = { keystorePassword: (0, _v().default)().replace(/-/g, ''), keyPassword: (0, _v().default)().replace(/-/g, ''), keyAlias: Buffer.from(experienceName).toString('base64'), keystorePath: uploadKeystorePath }; await createKeystore(keystoreData, androidPackage); return keystoreData; } //# sourceMappingURL=../__sourcemaps__/credentials/AndroidCredentials.js.map