crypto.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /**
  2. * @node crypto
  3. * @name Crypto
  4. * @category crypto
  5. * @version 1.0.0
  6. * @description Hash data, generate HMACs, and perform cryptographic operations for data integrity and message authentication
  7. * @icon lock
  8. */
  9. const configSchema = {
  10. type: 'object',
  11. properties: {
  12. operation: {
  13. type: 'string',
  14. title: 'Operation',
  15. enum: ['hash', 'hmac', 'random', 'encrypt', 'decrypt'],
  16. enumLabels: ['Hash', 'HMAC', 'Random Generation', 'Encrypt (Coming Soon)', 'Decrypt (Coming Soon)'],
  17. default: 'hash',
  18. description: 'Cryptographic operation to perform'
  19. },
  20. algorithm: {
  21. type: 'string',
  22. title: 'Algorithm',
  23. enum: ['md5', 'sha1', 'sha256', 'sha384', 'sha512'],
  24. enumLabels: ['MD5', 'SHA-1', 'SHA-256', 'SHA-384', 'SHA-512'],
  25. default: 'sha256',
  26. description: 'Hash algorithm to use',
  27. showWhen: { field: 'operation', value: ['hash', 'hmac'] }
  28. },
  29. outputFormat: {
  30. type: 'string',
  31. title: 'Output Format',
  32. enum: ['hex', 'base64'],
  33. enumLabels: ['Hexadecimal', 'Base64'],
  34. default: 'hex',
  35. description: 'Format of the output hash or HMAC',
  36. showWhen: { field: 'operation', value: ['hash', 'hmac'] }
  37. },
  38. secretKey: {
  39. type: 'string',
  40. title: 'Secret Key',
  41. description: 'Secret key for HMAC generation. Supports {{variable}} interpolation.',
  42. showWhen: { field: 'operation', value: 'hmac' }
  43. },
  44. randomLength: {
  45. type: 'number',
  46. title: 'Random Bytes Length',
  47. default: 32,
  48. description: 'Number of random bytes to generate (1-1024)',
  49. showWhen: { field: 'operation', value: 'random' }
  50. },
  51. randomFormat: {
  52. type: 'string',
  53. title: 'Random Output Format',
  54. enum: ['hex', 'base64', 'uuid'],
  55. enumLabels: ['Hexadecimal', 'Base64', 'UUID v4'],
  56. default: 'hex',
  57. description: 'Format of the random output',
  58. showWhen: { field: 'operation', value: 'random' }
  59. }
  60. },
  61. required: ['operation']
  62. };
  63. const inputSchema = {
  64. type: 'object',
  65. properties: {
  66. data: {
  67. type: 'any',
  68. description: 'Data to hash or process. Can be a string or will be JSON stringified.'
  69. },
  70. secretKey: {
  71. type: 'string',
  72. description: 'Override secret key for HMAC from input'
  73. }
  74. }
  75. };
  76. const outputSchema = {
  77. type: 'object',
  78. properties: {
  79. result: {
  80. type: 'string',
  81. description: 'The cryptographic operation result'
  82. },
  83. algorithm: {
  84. type: 'string',
  85. description: 'Algorithm used for the operation'
  86. },
  87. operation: {
  88. type: 'string',
  89. description: 'Operation that was performed'
  90. },
  91. format: {
  92. type: 'string',
  93. description: 'Output format (hex or base64)'
  94. },
  95. inputLength: {
  96. type: 'number',
  97. description: 'Length of the input data in bytes'
  98. }
  99. }
  100. };
  101. function interpolate(template, data) {
  102. if (typeof template !== 'string') return template;
  103. return template.replace(/\{\{([^}]+)\}\}/g, (match, key) => {
  104. const keys = key.trim().split('.');
  105. let value = data;
  106. for (const k of keys) {
  107. if (value && typeof value === 'object' && k in value) {
  108. value = value[k];
  109. } else {
  110. return match;
  111. }
  112. }
  113. return value !== undefined ? String(value) : match;
  114. });
  115. }
  116. async function execute(config, input, context) {
  117. const operation = config.operation || 'hash';
  118. if (operation === 'encrypt' || operation === 'decrypt') {
  119. throw new Error('Encrypt and Decrypt operations are not yet implemented. Coming soon.');
  120. }
  121. if (operation === 'random') {
  122. const format = config.randomFormat || 'hex';
  123. if (format === 'uuid') {
  124. const uuid = smartbotic.crypto.randomUUID();
  125. smartbotic.log.info('Generated random UUID');
  126. return {
  127. result: uuid,
  128. operation: 'random',
  129. format: 'uuid'
  130. };
  131. }
  132. const length = config.randomLength || 32;
  133. if (length < 1 || length > 1024) {
  134. throw new Error('Random length must be between 1 and 1024');
  135. }
  136. const randomHex = smartbotic.crypto.randomBytes(length);
  137. let result = randomHex;
  138. if (format === 'base64') {
  139. let binary = '';
  140. for (let i = 0; i < randomHex.length; i += 2) {
  141. binary += String.fromCharCode(parseInt(randomHex.substr(i, 2), 16));
  142. }
  143. result = smartbotic.utils.base64Encode(binary);
  144. }
  145. smartbotic.log.info('Generated ' + length + ' random bytes in ' + format + ' format');
  146. return {
  147. result: result,
  148. operation: 'random',
  149. format: format,
  150. inputLength: length
  151. };
  152. }
  153. const inputData = input.data !== undefined ? input.data : input;
  154. let dataStr;
  155. if (typeof inputData === 'string') {
  156. dataStr = inputData;
  157. } else if (inputData === null || inputData === undefined) {
  158. throw new Error('No data provided for ' + operation + ' operation');
  159. } else {
  160. dataStr = JSON.stringify(inputData);
  161. }
  162. const algorithm = config.algorithm || 'sha256';
  163. const outputFormat = config.outputFormat || 'hex';
  164. if (operation === 'hash') {
  165. smartbotic.log.info('Hashing ' + dataStr.length + ' bytes with ' + algorithm.toUpperCase());
  166. const result = smartbotic.crypto.hash(dataStr, algorithm, outputFormat);
  167. return {
  168. result: result,
  169. algorithm: algorithm,
  170. operation: 'hash',
  171. format: outputFormat,
  172. inputLength: dataStr.length
  173. };
  174. }
  175. if (operation === 'hmac') {
  176. let secretKey = input.secretKey || config.secretKey;
  177. if (secretKey && typeof secretKey === 'string') {
  178. secretKey = interpolate(secretKey, input);
  179. }
  180. if (!secretKey) {
  181. throw new Error('Secret key is required for HMAC operation');
  182. }
  183. smartbotic.log.info('Generating HMAC-' + algorithm.toUpperCase() + ' for ' + dataStr.length + ' bytes');
  184. const result = smartbotic.crypto.hmac(dataStr, secretKey, algorithm, outputFormat);
  185. return {
  186. result: result,
  187. algorithm: algorithm,
  188. operation: 'hmac',
  189. format: outputFormat,
  190. inputLength: dataStr.length
  191. };
  192. }
  193. throw new Error('Unknown operation: ' + operation);
  194. }
  195. module.exports = { configSchema, inputSchema, outputSchema, execute };