helper.js

  1. 'use strict'
  2. var pathlib = require('path')
  3. var fs = require('fs')
  4. var crypto = require('crypto')
  5. var osTmpdir = require('os-tmpdir')
  6. var tempDir = process.env.PEMJS_TMPDIR || osTmpdir()
  7. /**
  8. * pem helper module
  9. *
  10. * @module helper
  11. */
  12. /**
  13. * helper function to check is the string a number or not
  14. * @param {String} str String that should be checked to be a number
  15. */
  16. module.exports.isNumber = function (str) {
  17. if (Array.isArray(str)) {
  18. return false
  19. }
  20. /*
  21. var bstr = str && str.toString()
  22. str = str + ''
  23. return bstr - parseFloat(bstr) + 1 >= 0 &&
  24. !/^\s+|\s+$/g.test(str) && /^\d+$/g.test(str) &&
  25. !isNaN(str) && !isNaN(parseFloat(str))
  26. */
  27. return /^\d+$/g.test(str)
  28. }
  29. /**
  30. * helper function to check is the string a hexaceximal value
  31. * @param {String} hex String that should be checked to be a hexaceximal
  32. */
  33. module.exports.isHex = function isHex (hex) {
  34. return /^(0x){0,1}([0-9A-F]{1,40}|[0-9A-F]{1,40})$/gi.test(hex)
  35. }
  36. /**
  37. * helper function to convert a string to a hexaceximal value
  38. * @param {String} str String that should be converted to a hexaceximal
  39. */
  40. module.exports.toHex = function toHex (str) {
  41. var hex = ''
  42. for (var i = 0; i < str.length; i++) {
  43. hex += '' + str.charCodeAt(i).toString(16)
  44. }
  45. return hex
  46. }
  47. // cipherPassword returns an array of supported ciphers.
  48. /**
  49. * list of supported ciphers
  50. * @type {Array}
  51. */
  52. module.exports.ciphers = ['aes128', 'aes192', 'aes256', 'camellia128', 'camellia192', 'camellia256', 'des', 'des3', 'idea']
  53. var ciphers = module.exports.ciphers
  54. /**
  55. * Creates a PasswordFile to hide the password form process infos via `ps auxf` etc.
  56. * @param {Object} options object of cipher, password and passType, mustPass, {cipher:'aes128', password:'xxxx', passType:"in/out/word"}, if the object empty we do nothing
  57. * @param {String} options.cipher cipher like 'aes128', 'aes192', 'aes256', 'camellia128', 'camellia192', 'camellia256', 'des', 'des3', 'idea'
  58. * @param {String} options.password password can be empty or at last 4 to 1023 chars
  59. * @param {String} options.passType passType: can be in/out/word for passIN/passOUT/passWORD
  60. * @param {Boolean} options.mustPass mustPass is used when you need to set the pass like as "-password pass:" most needed when empty password
  61. * @param {Object} params params will be extended with the data that need for the openssl command. IS USED AS POINTER!
  62. * @param {String} PasswordFileArray PasswordFileArray is an array of filePaths that later need to deleted ,after the openssl command. IS USED AS POINTER!
  63. * @return {Boolean} result
  64. */
  65. module.exports.createPasswordFile = function (options, params, PasswordFileArray) {
  66. if (!options || !Object.prototype.hasOwnProperty.call(options, 'password') || !Object.prototype.hasOwnProperty.call(options, 'passType') || !/^(word|in|out)$/.test(options.passType)) {
  67. return false
  68. }
  69. var PasswordFile = pathlib.join(tempDir, crypto.randomBytes(20).toString('hex'))
  70. PasswordFileArray.push(PasswordFile)
  71. options.password = options.password.trim()
  72. if (options.password === '') {
  73. options.mustPass = true
  74. }
  75. if (options.cipher && (ciphers.indexOf(options.cipher) !== -1)) {
  76. params.push('-' + options.cipher)
  77. }
  78. params.push('-pass' + options.passType)
  79. if (options.mustPass) {
  80. params.push('pass:' + options.password)
  81. } else {
  82. fs.writeFileSync(PasswordFile, options.password)
  83. params.push('file:' + PasswordFile)
  84. }
  85. return true
  86. }
  87. /**
  88. * Deletes a file or an array of files
  89. * @param {Array} files array of files that shoudld be deleted
  90. * @param {errorCallback} callback Callback function with an error object
  91. */
  92. module.exports.deleteTempFiles = function (files, callback) {
  93. var rmFiles = []
  94. if (typeof files === 'string') {
  95. rmFiles.push(files)
  96. } else if (Array.isArray(files)) {
  97. rmFiles = files
  98. } else {
  99. return callback(new Error('Unexcepted files parameter type; only string or array supported'))
  100. }
  101. var deleteSeries = function (list, finalCallback) {
  102. if (list.length) {
  103. var file = list.shift()
  104. var myCallback = function (err) {
  105. if (err && err.code === 'ENOENT') {
  106. // file doens't exist
  107. return deleteSeries(list, finalCallback)
  108. } else if (err) {
  109. // other errors, e.g. maybe we don't have enough permission
  110. return finalCallback(err)
  111. } else {
  112. return deleteSeries(list, finalCallback)
  113. }
  114. }
  115. if (file && typeof file === 'string') {
  116. fs.unlink(file, myCallback)
  117. } else {
  118. return deleteSeries(list, finalCallback)
  119. }
  120. } else {
  121. return finalCallback(null) // no errors
  122. }
  123. }
  124. deleteSeries(rmFiles, callback)
  125. }
  126. /**
  127. * Callback for return an error object.
  128. * @callback errorCallback
  129. * @param {Error} err - An Error Object or null
  130. */