2

I'm actually working on a new project based on netsuite product. I'm trying to encrypt a message using hmac sha256.

What's is the simple way to do it considering that I have the stringToEncrypt and a key.

I've read the documentation in Netsuite but I'm still stucked...

There is my function

function toHmacSHA256Base64(toCrypt, key) {
        var inputString = toCrypt;
        var myGuid = key;
        var sKey = crypto.createSecretKey({
            guid: myGuid,
            encoding: encode.Encoding.UTF_8
        });
        var hmacSHA256 = crypto.createHmac({
            algorithm: 'SHA256',
            key: sKey
        });
        hmacSHA256.update({
            input: inputString,
            inputEncoding: encode.Encoding.BASE_64
        });
        var digestSHA256 = hmacSHA256.digest({
            outputEncoding: encode.Encoding.HEX
        });
        return digestSHA256;
};

of course behind the word crypto I use the module 'N/crypto' and encode 'N/encode'. Thx a lot.

Arigui Ahmed
  • 393
  • 6
  • 14

1 Answers1

5

That's roughly correct and looks exactly like the sample from the NS help. If you have a string then you probably want inputEncoding:encode.Encoding.UTF_8 for the update call.

What's missing is how to generate the guid of the secret key. For that you use a suitelet. Note the addSecretKeyField not the addCredentialField of the NS help:

/**
 *@NApiVersion 2.x
 *@NScriptType Suitelet
 */
define(['N/ui/serverWidget', './config.js'],
    function(serverWidget, config) {
        function onRequest(context) {
            if (context.request.method === 'GET') {
                var form = serverWidget.createForm({
                    title: 'SFTP Password'
                });

                form.addSecretKeyField({
                    id : 'username',
                    label : 'Pwd',
                    restrictToScriptIds : config.targetScript,
                    restrictToCurrentUser : false
                });
                form.addSubmitButton({
                    label: 'Submit Button'
                });

                context.response.writePage(form);
            } else {
                var textField = context.request.parameters.username;
                context.response.write('You have entered: ' + textField);
            }
        }

        return {
            onRequest: onRequest
        };
    });

FWIW encrypt is the wrong term here. You are creating a hash of the data which will be used for ensuring data integrity. You cannot decrypt a hash.

Once a GUID for a key has been generated I just store it in a config file (same one as is used for the script list above.

in TypeScript it looks like:

/**
 * config.js
 * @NApiVersion 2.x
 */

export var config =  {

    'host': '162.242.144.xxx',
    'userName': 'unsername',
    'targetScript': ['customscript_transmit_dsv_943', 'customscript_transmit_dsv_940', 'customscript_retrieve_dsv_944'],
    'hostKey': 'AAAAB3Nza...Wz'
};

Then everything except the config.xs files can be stored in version control. Audience needs to be set appropriately on the files used in the script.

bknights
  • 14,408
  • 2
  • 18
  • 31
  • I'm attempting to calculate an HMAC within a RESTlet, and there's no form involved. I'm attempting to call out to an external web service, and that web service requires that I send an HMAC. I see no way to create the secretKey without a form being involved. Is there? I think I'm going to have to import routines from crypto-js to do this simple thing. – Larry Silverman Mar 10 '18 at 22:00
  • The form is just used once to get a keystore reference for the hmac key. I have gone the external library route for both ss1 and ss2 though and that also works – bknights Mar 11 '18 at 05:38
  • Are you saying this method permanently stores a secret in Netsuite which you can then refer to with the returned GUID? Are those secrets visible anywhere in the Admin UI? I've searched the docs and Netsuite and I can't find obvious place to store secrets for use cases like external authentication. – Larry Silverman Mar 11 '18 at 19:22
  • That’s right. The returned GUID is a reference to the uploaded secret. You pass the GUID to Netsuite’s API where you’d expect to pass the secret. – bknights Mar 11 '18 at 21:16
  • How do you manage these secrets once they are stored in Netsuite? Do you need to maintain a spreadsheet somewhere outside of Netsuite to map your GUIDs to the secrets they contain? – Larry Silverman Mar 12 '18 at 15:08
  • I use a config file. Just added an example – bknights Mar 12 '18 at 16:11
  • Please help me understand the scope of this secret-setting SuiteScript you've created? Let's say you need to call out to 10 different external web services, and you wish to store those 10 unique secrets in Netsuite. Would you copy/paste/deploy this script 10 times, once for each unique purpose? Or would you reuse the single script, but rewriting the form names and labels and the .config.js for each unique use case? – Larry Silverman Mar 12 '18 at 17:02
  • If I had 10 I'd probably create a custom record that contained at least the script ids I was going to use and some way to link the custom record to the deployment so the deployment could easily look up its GUIDs. Then instead of having the form just return the GUID you'd start by selecting a record and when you've vaulted the HMAC secret the suitelet response would store the GUID for you. – bknights Mar 12 '18 at 20:29