UNPKG

dynatrace-cordova-outsystems-plugin

Version:

This plugin gives you the ability to use the Dynatrace instrumentation in your hybrid application (Cordova, Ionic, ..). It uses the Mobile Agent, the JavaScript Agent and the Javascript Bridge. The Mobile Agent will give you all device specific values con

288 lines (266 loc) 9.19 kB
// Copyright 2017 Joyent, Inc. module.exports = { read: read, write: write }; var assert = require('assert-plus'); var Buffer = require('safer-buffer').Buffer; var Key = require('../key'); var PrivateKey = require('../private-key'); var utils = require('../utils'); var SSHBuffer = require('../ssh-buffer'); var Dhe = require('../dhe'); var supportedAlgos = { 'rsa-sha1' : 5, 'rsa-sha256' : 8, 'rsa-sha512' : 10, 'ecdsa-p256-sha256' : 13, 'ecdsa-p384-sha384' : 14 /* * ed25519 is hypothetically supported with id 15 * but the common tools available don't appear to be * capable of generating/using ed25519 keys */ }; var supportedAlgosById = {}; Object.keys(supportedAlgos).forEach(function (k) { supportedAlgosById[supportedAlgos[k]] = k.toUpperCase(); }); function read(buf, options) { if (typeof (buf) !== 'string') { assert.buffer(buf, 'buf'); buf = buf.toString('ascii'); } var lines = buf.split('\n'); if (lines[0].match(/^Private-key-format\: v1/)) { var algElems = lines[1].split(' '); var algoNum = parseInt(algElems[1], 10); var algoName = algElems[2]; if (!supportedAlgosById[algoNum]) throw (new Error('Unsupported algorithm: ' + algoName)); return (readDNSSECPrivateKey(algoNum, lines.slice(2))); } // skip any comment-lines var line = 0; /* JSSTYLED */ while (lines[line].match(/^\;/)) line++; // we should now have *one single* line left with our KEY on it. if ((lines[line].match(/\. IN KEY /) || lines[line].match(/\. IN DNSKEY /)) && lines[line+1].length === 0) { return (readRFC3110(lines[line])); } throw (new Error('Cannot parse dnssec key')); } function readRFC3110(keyString) { var elems = keyString.split(' '); //unused var flags = parseInt(elems[3], 10); //unused var protocol = parseInt(elems[4], 10); var algorithm = parseInt(elems[5], 10); if (!supportedAlgosById[algorithm]) throw (new Error('Unsupported algorithm: ' + algorithm)); var base64key = elems.slice(6, elems.length).join(); var keyBuffer = Buffer.from(base64key, 'base64'); if (supportedAlgosById[algorithm].match(/^RSA-/)) { // join the rest of the body into a single base64-blob var publicExponentLen = keyBuffer.readUInt8(0); if (publicExponentLen != 3 && publicExponentLen != 1) throw (new Error('Cannot parse dnssec key: ' + 'unsupported exponent length')); var publicExponent = keyBuffer.slice(1, publicExponentLen+1); publicExponent = utils.mpNormalize(publicExponent); var modulus = keyBuffer.slice(1+publicExponentLen); modulus = utils.mpNormalize(modulus); // now, make the key var rsaKey = { type: 'rsa', parts: [] }; rsaKey.parts.push({ name: 'e', data: publicExponent}); rsaKey.parts.push({ name: 'n', data: modulus}); return (new Key(rsaKey)); } if (supportedAlgosById[algorithm] === 'ECDSA-P384-SHA384' || supportedAlgosById[algorithm] === 'ECDSA-P256-SHA256') { var curve = 'nistp384'; var size = 384; if (supportedAlgosById[algorithm].match(/^ECDSA-P256-SHA256/)) { curve = 'nistp256'; size = 256; } var ecdsaKey = { type: 'ecdsa', curve: curve, size: size, parts: [ {name: 'curve', data: Buffer.from(curve) }, {name: 'Q', data: utils.ecNormalize(keyBuffer) } ] }; return (new Key(ecdsaKey)); } throw (new Error('Unsupported algorithm: ' + supportedAlgosById[algorithm])); } function elementToBuf(e) { return (Buffer.from(e.split(' ')[1], 'base64')); } function readDNSSECRSAPrivateKey(elements) { var rsaParams = {}; elements.forEach(function (element) { if (element.split(' ')[0] === 'Modulus:') rsaParams['n'] = elementToBuf(element); else if (element.split(' ')[0] === 'PublicExponent:') rsaParams['e'] = elementToBuf(element); else if (element.split(' ')[0] === 'PrivateExponent:') rsaParams['d'] = elementToBuf(element); else if (element.split(' ')[0] === 'Prime1:') rsaParams['p'] = elementToBuf(element); else if (element.split(' ')[0] === 'Prime2:') rsaParams['q'] = elementToBuf(element); else if (element.split(' ')[0] === 'Exponent1:') rsaParams['dmodp'] = elementToBuf(element); else if (element.split(' ')[0] === 'Exponent2:') rsaParams['dmodq'] = elementToBuf(element); else if (element.split(' ')[0] === 'Coefficient:') rsaParams['iqmp'] = elementToBuf(element); }); // now, make the key var key = { type: 'rsa', parts: [ { name: 'e', data: utils.mpNormalize(rsaParams['e'])}, { name: 'n', data: utils.mpNormalize(rsaParams['n'])}, { name: 'd', data: utils.mpNormalize(rsaParams['d'])}, { name: 'p', data: utils.mpNormalize(rsaParams['p'])}, { name: 'q', data: utils.mpNormalize(rsaParams['q'])}, { name: 'dmodp', data: utils.mpNormalize(rsaParams['dmodp'])}, { name: 'dmodq', data: utils.mpNormalize(rsaParams['dmodq'])}, { name: 'iqmp', data: utils.mpNormalize(rsaParams['iqmp'])} ] }; return (new PrivateKey(key)); } function readDNSSECPrivateKey(alg, elements) { if (supportedAlgosById[alg].match(/^RSA-/)) { return (readDNSSECRSAPrivateKey(elements)); } if (supportedAlgosById[alg] === 'ECDSA-P384-SHA384' || supportedAlgosById[alg] === 'ECDSA-P256-SHA256') { var d = Buffer.from(elements[0].split(' ')[1], 'base64'); var curve = 'nistp384'; var size = 384; if (supportedAlgosById[alg] === 'ECDSA-P256-SHA256') { curve = 'nistp256'; size = 256; } // DNSSEC generates the public-key on the fly (go calculate it) var publicKey = utils.publicFromPrivateECDSA(curve, d); var Q = publicKey.part['Q'].data; var ecdsaKey = { type: 'ecdsa', curve: curve, size: size, parts: [ {name: 'curve', data: Buffer.from(curve) }, {name: 'd', data: d }, {name: 'Q', data: Q } ] }; return (new PrivateKey(ecdsaKey)); } throw (new Error('Unsupported algorithm: ' + supportedAlgosById[alg])); } function dnssecTimestamp(date) { var year = date.getFullYear() + ''; //stringify var month = (date.getMonth() + 1); var timestampStr = year + month + date.getUTCDate(); timestampStr += '' + date.getUTCHours() + date.getUTCMinutes(); timestampStr += date.getUTCSeconds(); return (timestampStr); } function rsaAlgFromOptions(opts) { if (!opts || !opts.hashAlgo || opts.hashAlgo === 'sha1') return ('5 (RSASHA1)'); else if (opts.hashAlgo === 'sha256') return ('8 (RSASHA256)'); else if (opts.hashAlgo === 'sha512') return ('10 (RSASHA512)'); else throw (new Error('Unknown or unsupported hash: ' + opts.hashAlgo)); } function writeRSA(key, options) { // if we're missing parts, add them. if (!key.part.dmodp || !key.part.dmodq) { utils.addRSAMissing(key); } var out = ''; out += 'Private-key-format: v1.3\n'; out += 'Algorithm: ' + rsaAlgFromOptions(options) + '\n'; var n = utils.mpDenormalize(key.part['n'].data); out += 'Modulus: ' + n.toString('base64') + '\n'; var e = utils.mpDenormalize(key.part['e'].data); out += 'PublicExponent: ' + e.toString('base64') + '\n'; var d = utils.mpDenormalize(key.part['d'].data); out += 'PrivateExponent: ' + d.toString('base64') + '\n'; var p = utils.mpDenormalize(key.part['p'].data); out += 'Prime1: ' + p.toString('base64') + '\n'; var q = utils.mpDenormalize(key.part['q'].data); out += 'Prime2: ' + q.toString('base64') + '\n'; var dmodp = utils.mpDenormalize(key.part['dmodp'].data); out += 'Exponent1: ' + dmodp.toString('base64') + '\n'; var dmodq = utils.mpDenormalize(key.part['dmodq'].data); out += 'Exponent2: ' + dmodq.toString('base64') + '\n'; var iqmp = utils.mpDenormalize(key.part['iqmp'].data); out += 'Coefficient: ' + iqmp.toString('base64') + '\n'; // Assume that we're valid as-of now var timestamp = new Date(); out += 'Created: ' + dnssecTimestamp(timestamp) + '\n'; out += 'Publish: ' + dnssecTimestamp(timestamp) + '\n'; out += 'Activate: ' + dnssecTimestamp(timestamp) + '\n'; return (Buffer.from(out, 'ascii')); } function writeECDSA(key, options) { var out = ''; out += 'Private-key-format: v1.3\n'; if (key.curve === 'nistp256') { out += 'Algorithm: 13 (ECDSAP256SHA256)\n'; } else if (key.curve === 'nistp384') { out += 'Algorithm: 14 (ECDSAP384SHA384)\n'; } else { throw (new Error('Unsupported curve')); } var base64Key = key.part['d'].data.toString('base64'); out += 'PrivateKey: ' + base64Key + '\n'; // Assume that we're valid as-of now var timestamp = new Date(); out += 'Created: ' + dnssecTimestamp(timestamp) + '\n'; out += 'Publish: ' + dnssecTimestamp(timestamp) + '\n'; out += 'Activate: ' + dnssecTimestamp(timestamp) + '\n'; return (Buffer.from(out, 'ascii')); } function write(key, options) { if (PrivateKey.isPrivateKey(key)) { if (key.type === 'rsa') { return (writeRSA(key, options)); } else if (key.type === 'ecdsa') { return (writeECDSA(key, options)); } else { throw (new Error('Unsupported algorithm: ' + key.type)); } } else if (Key.isKey(key)) { /* * RFC3110 requires a keyname, and a keytype, which we * don't really have a mechanism for specifying such * additional metadata. */ throw (new Error('Format "dnssec" only supports ' + 'writing private keys')); } else { throw (new Error('key is not a Key or PrivateKey')); } }