UNPKG

wooooosik6

Version:

Instant live reload tool for Tizen Web Application development

419 lines (365 loc) 14.7 kB
/** * Code from SRC-Nanjing */ const fs = require('fs'); const path = require('path'); const mkdirp = require('mkdirp'); const forge = require('node-forge'); const util = require('../util'); const cryptUtil = require('./cryptUtil'); const parseString = require('xml2js').parseString; const witsPath = path.join(util.WITS_BASE_PATH, '../', 'container'); const moduleName = 'P12ToPem'; const certificatesPath = path.join( witsPath, '/.resource/certificate-generator/certificates/' ); const ACTIVE_PEM_FILE = { AUTHOR_KEY_FILE: path.join( certificatesPath, 'developer/active_cert/tizen_developer_private_key.pem' ), AUTHOR_CERT_FILE: path.join( certificatesPath + 'developer/active_cert/tizen_developer_cert.pem' ), DISTRIBUTOR_KEY_FILE: path.join( certificatesPath + 'distributor/active_cert/tizen_distributor_private_key.pem' ), DISTRIBUTOR_CERT_FILE: path.join( certificatesPath + 'distributor/active_cert/tizen_distributor_cert.pem' ), DISTRIBUTOR2_KEY_FILE: path.join( certificatesPath + 'distributor/active_cert/tizen_distributor2_private_key.pem' ), DISTRIBUTOR2_CERT_FILE: path.join( certificatesPath + 'distributor/active_cert/tizen_distributor2_cert.pem' ) }; exports.ACTIVE_PEM_FILE = ACTIVE_PEM_FILE; let activeProfile = ''; let authorFile = ''; let distributorFile = ''; let authorPassword = ''; let distributorPassword = ''; let distributorFile2 = ''; let distributorPassword2 = ''; /** * Extract the private key from a PKCS12 file. * @param {Buffer|String(Base64-encoded)} p12Buffer * The PKCS12 file as a buffer or base-64 encoded string. * @param {String} password The password for the PKCS12 file. * @param {String} type The type of PKCS12 file ,developer or distributor. * @param {String} keyfile The pem key file path. * @param {String} certfile The pem cert file path. */ function p12ToPem(p12Buffer, password, type, keyfile, certfile) { console.log( moduleName, '================Converting ' + type + ' P12 file to Pem file' ); var entry = parseCertificate(p12Buffer, password); if (!entry) { console.error(moduleName, 'Parse Certififate failed'); throw 'Parse Certififate failed'; } //Write map content to file if (entry.privateKey) { var privateKeyP12Pem = forge.pki.privateKeyToPem(entry.privateKey); //console.log('\nPrivate Key:'); //console.log(privateKeyP12Pem); createDir(path.join(certificatesPath + type, 'active_cert')); fs.writeFileSync(keyfile, privateKeyP12Pem, 'utf8'); console.log( moduleName, 'Converted pem private key file is in ' + keyfile ); } else { console.log(''); } //console.log('certChain.length:'+entry.certChain.length); var certChainData = ''; if (entry.certChain.length > 0) { var certChain = entry.certChain; for (var i = 0; i < certChain.length; ++i) { var certP12Pem = forge.pki.certificateToPem(certChain[i]); certChainData = certChainData + certP12Pem; } } //console.log('\nCert Content:'); //console.log(certChainData); createDir(path.join(certificatesPath + type, 'active_cert')); fs.writeFileSync(certfile, certChainData, 'utf8'); console.log(moduleName, 'Converted pem cert file is in ' + certfile); } function parseCertificate(p12Buffer, password) { console.log(moduleName, 'Start Parse Certificate'); var p12Der = p12Buffer.toString(); var pkcs12Asn1; var pkcs12; try { pkcs12Asn1 = forge.asn1.fromDer(p12Der); pkcs12 = forge.pkcs12.pkcs12FromAsn1(pkcs12Asn1, password || ''); } catch (ex) { //For case p12 author cert created by Tizen Studio var p12Base64 = p12Buffer.toString('base64'); p12Der = forge.util.decode64(p12Base64); try { pkcs12Asn1 = forge.asn1.fromDer(p12Der); pkcs12 = forge.pkcs12.pkcs12FromAsn1(pkcs12Asn1, password || ''); } catch (e) { console.error( moduleName, 'Parse certificate failed, the password may not match the certificate' ); console.error(moduleName, ex.message); throw e; } } // load keypair and cert chain from safe content(s) and map to key ID var map = {}; for (var sci = 0; sci < pkcs12.safeContents.length; ++sci) { var safeContents = pkcs12.safeContents[sci]; var localKeyId = null; for (var sbi = 0; sbi < safeContents.safeBags.length; ++sbi) { var safeBag = safeContents.safeBags[sbi]; if (safeBag.attributes.localKeyId) { localKeyId = forge.util.bytesToHex( safeBag.attributes.localKeyId[0] ); if (!(localKeyId in map)) { map[localKeyId] = { privateKey: null, certChain: [] }; } } // this bag has a private key if (safeBag.type === forge.pki.oids.pkcs8ShroudedKeyBag) { map[localKeyId].privateKey = safeBag.key; } else if (safeBag.type === forge.pki.oids.certBag) { // this bag has a certificate map[localKeyId].certChain.push(safeBag.cert); } } } var entry; //Get cert attributes for (var localKeyId in map) { entry = map[localKeyId]; } return entry; } function getCertificateInfo(certPath, password) { var afterYear = ''; var issuerName = ''; if (fs.existsSync(certPath)) { var p12Buffer = fs.readFileSync(certPath); var decodePass = cryptUtil.decryptPassword(password); var entry = parseCertificate(p12Buffer, decodePass); if (!entry) { console.error(moduleName, 'Parse Certififate failed'); throw 'Parse Certififate failed'; } var certChain = entry.certChain; certChain = certChain.slice(0); var certs = certChain.slice(0); var parsecert = certChain.shift(); //console.log('cert.validity.notBefore :'+parsecert.validity.notBefore); //var beforeDate = parsecert.validity.notBefore; var afterDate = parsecert.validity.notAfter; afterYear = afterDate.toString(); afterYear = afterYear.substring(3, 15); issuerName = ''; for (var j = 0; j < parsecert.issuer.attributes.length; j++) { var name = parsecert.issuer.attributes[j].name; var value = parsecert.issuer.attributes[j].value; if (name == 'commonName') { issuerName = value; break; } } } else { var noCert = certPath + " is not exist ,can't get the certificate info"; console.log(moduleName, noCert); throw noCert; } return { afterYear, issuerName }; } exports.getCertificateInfo = getCertificateInfo; // load and parse profiles.xml function loadProfile(profilePath) { console.log(moduleName, '================ Load Profile'); var profileFlag = false; authorFile = ''; distributorFile = ''; activeProfile = ''; authorPassword = ''; distributorPassword = ''; distributorFile2 = ''; distributorPassword2 = ''; authorCa = ''; distributorCa = ''; distributorCa2 = ''; isSamsungCertificate = false; certificateFilePath = ''; if (fs.existsSync(profilePath)) { console.log(moduleName, 'Profile file path:' + profilePath); var data = fs.readFileSync(profilePath, 'utf-8'); //parse profiles.xml file to get author and distributor p12 certificate file parseString(data, { explicitArray: false }, function (err, result) { var jsonData = JSON.stringify(result); var jsonArray = JSON.parse(jsonData); activeProfile = jsonArray.profiles.$.active; if (typeof activeProfile != 'undefined') { console.log(moduleName, 'Active profile name:' + activeProfile); var profiles = jsonArray.profiles.profile; var profileItems; if (profiles && !profiles.length) { //For only one profile case profileItems = profiles.profileitem; } else if (profiles && profiles.length) { //For multiple profile case for (var i = 0; i < profiles.length; i++) { var name = profiles[i].$.name; if (activeProfile == name) { profileItems = profiles[i].profileitem; } } } if ( typeof profileItems != 'undefined' && profileItems.length > 2 ) { console.log( moduleName, 'Find active profile:' + activeProfile ); var tmpAuthorFile = __dirname + profileItems[0].$.key; if ( !fs.existsSync(profileItems[0].$.key) && profileItems[0].$.key.length > 0 && fs.existsSync(tmpAuthorFile) ) { authorFile = tmpAuthorFile; } else { authorFile = profileItems[0].$.key; } var tmpDistributorFile = __dirname + profileItems[1].$.key; if ( !fs.existsSync(profileItems[1].$.key) && profileItems[1].$.key.length > 0 && fs.existsSync(tmpDistributorFile) ) { distributorFile = tmpDistributorFile; } else { distributorFile = profileItems[1].$.key; } var tmpDistributorFile2 = __dirname + profileItems[2].$.key; if (fs.existsSync(profileItems[2].$.key)) { distributorFile2 = profileItems[2].$.key; } else if ( profileItems[2].$.key.length > 0 && fs.existsSync(tmpDistributorFile2) ) { distributorFile2 = tmpDistributorFile2; } authorPassword = profileItems[0].$.password; distributorPassword = profileItems[1].$.password; distributorPassword2 = profileItems[2].$.password; if ( fs.existsSync(authorFile) && fs.existsSync(distributorFile) ) { console.log( moduleName, 'Developer p12 File: ' + authorFile ); console.log( moduleName, 'Distributor p12 File: ' + distributorFile ); profileFlag = true; } } } }); } return profileFlag; } exports.loadProfile = loadProfile; function getDistributorFile2() { return distributorFile2; } exports.getDistributorFile2 = getDistributorFile2; // Handle 'Create Web Project' commands function checkActiveProfile(profilePath) { console.log(moduleName, '================ Check Active Profile'); var flag = loadProfile(profilePath); if (flag) { var authorP12Buffer = fs.readFileSync(authorFile); var distributorP12Buffer = fs.readFileSync(distributorFile); console.debug(moduleName, 'authorPassword:' + authorPassword); console.debug(moduleName, 'distributorPassword:' + distributorPassword); var decodedAuthorPass = cryptUtil.decryptPassword(authorPassword); var decodedDistributorPass = cryptUtil.decryptPassword( distributorPassword ); console.debug(moduleName, 'decodedAuthorPass:' + decodedAuthorPass); console.debug( moduleName, 'decodedDistributorPass:' + decodedDistributorPass ); p12ToPem( authorP12Buffer, decodedAuthorPass, 'developer', ACTIVE_PEM_FILE.AUTHOR_KEY_FILE, ACTIVE_PEM_FILE.AUTHOR_CERT_FILE ); p12ToPem( distributorP12Buffer, decodedDistributorPass, 'distributor', ACTIVE_PEM_FILE.DISTRIBUTOR_KEY_FILE, ACTIVE_PEM_FILE.DISTRIBUTOR_CERT_FILE ); console.log(distributorFile2); if (fs.existsSync(distributorFile2)) { var distributorP12Buffer2 = fs.readFileSync(distributorFile2); var decodeDistributor2Pass = cryptUtil.decryptPassword( distributorPassword2 ); p12ToPem( distributorP12Buffer2, decodeDistributor2Pass, 'distributor', ACTIVE_PEM_FILE.DISTRIBUTOR2_KEY_FILE, ACTIVE_PEM_FILE.DISTRIBUTOR2_CERT_FILE ); } } else { var warningMsg = 'No Active certificate profile for building the package on ' + process.platform + ', you can create new profile or set active by Certificate Manager'; console.log(moduleName, warningMsg); throw warningMsg; } } exports.checkActiveProfile = checkActiveProfile; function createDir(dirPath) { if (!fs.existsSync(dirPath)) { console.log(moduleName, 'Create dir path:' + dirPath); try { mkdirp.sync(dirPath); } catch (ex) { console.debug(moduleName, ex.message); throw ex; } } else { //console.log(moduleName, dirPath+' is exist'); } } exports.createDir = createDir;