Is it necessary to use key derivation when using Node's 'crypto' module? Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 23, 2019 at 00:00UTC (8:00pm US/Eastern) Data science time! April 2019 and salary with experience The Ask Question Wizard is Live!When is a CDATA section necessary within a script tag?Java 256-bit AES Password-Based EncryptionHow to decide when to use Node.js?Javascript by reference vs. by valueIs Safari on iOS 6 caching $.ajax results?Using ursa (nodejs module) to generate a symmetric key?Camel PGP crypto and symmetric keysSymmetric Encryption with GPGMEDoes NodeJS https perform symmetric encryption of the trafficEncryption/decryption using publickey | Crypto Module | NodeJS

Disembodied hand growing fangs

How to tell that you are a giant?

Why wasn't DOSKEY integrated with COMMAND.COM?

What is a fractional matching?

Do I really need to have a message in a novel to appeal to readers?

Using audio cues to encourage good posture

What does it mean that physics no longer uses mechanical models to describe phenomena?

SF book about people trapped in a series of worlds they imagine

How does the math work when buying airline miles?

Did Deadpool rescue all of the X-Force?

Why is the AVR GCC compiler using a full `CALL` even though I have set the `-mshort-calls` flag?

What is the appropriate index architecture when forced to implement IsDeleted (soft deletes)?

How often does castling occur in grandmaster games?

How to compare two different files line by line in unix?

Denied boarding although I have proper visa and documentation. To whom should I make a complaint?

Why do early math courses focus on the cross sections of a cone and not on other 3D objects?

Is CEO the "profession" with the most psychopaths?

As a beginner, should I get a Squier Strat with a SSS config or a HSS?

Can anything be seen from the center of the Boötes void? How dark would it be?

Amount of permutations on an NxNxN Rubik's Cube

The code below, is it ill-formed NDR or is it well formed?

How fail-safe is nr as stop bytes?

How to write this math term? with cases it isn't working

Selecting user stories during sprint planning



Is it necessary to use key derivation when using Node's 'crypto' module?



Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 23, 2019 at 00:00UTC (8:00pm US/Eastern)
Data science time! April 2019 and salary with experience
The Ask Question Wizard is Live!When is a CDATA section necessary within a script tag?Java 256-bit AES Password-Based EncryptionHow to decide when to use Node.js?Javascript by reference vs. by valueIs Safari on iOS 6 caching $.ajax results?Using ursa (nodejs module) to generate a symmetric key?Camel PGP crypto and symmetric keysSymmetric Encryption with GPGMEDoes NodeJS https perform symmetric encryption of the trafficEncryption/decryption using publickey | Crypto Module | NodeJS



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








0















I need to implement symmetric encryption using a user's passphrase in a NodeJS application. When using crypto.createCipheriv(), do I need to perform some sort of key derivation on the passphrase to obtain a value for the key parameter, or is it sufficient to just pass the user's passphrase as-is and this is taken care of by the implementation?










share|improve this question






















  • Im not entirely understanding, what you want to do. you want to create a symmetric encryption using a passphrase of the user, and you will have it on the server side so will be able to use it as a seed in both sides? I'm not following what are you willing to do with these pieces. Are you willing to use a key separation technique or you just want to successfully and securely get a symmetric key?

    – Daniel Vega
    Mar 7 at 15:42






  • 1





    createCipheriv() doesn't modify the user specified key, so yes, if you have a password you should use a KDF.

    – t.m.adam
    Mar 7 at 18:08











  • @DanielVega - no, this is an Electron app and encryption is for data being synchronized

    – millimoose
    Mar 7 at 19:08











  • @t.m.adam Thanks, that’s probably closest to what I’m looking for. Is my intuition that not stretching the passphrase is a Bad Idea correct? (My current thinking is to shove the passphrase and the user ID - both generated using nanoid that claims to produce sound character distributions from a CSPRNG - into Argon2; with only the ID ever existing outside the user’s device as cleartext, the derived key cached on it, the passphrase as close to never as is possible on the platform.)

    – millimoose
    Mar 8 at 18:32






  • 1





    Yes, never use a password as key. Argon2 is a very good KDF, but it's not supported by crypto as far as I know. I'll post an answer using PBKDF2/scrypt if you're interested.

    – t.m.adam
    Mar 8 at 18:45

















0















I need to implement symmetric encryption using a user's passphrase in a NodeJS application. When using crypto.createCipheriv(), do I need to perform some sort of key derivation on the passphrase to obtain a value for the key parameter, or is it sufficient to just pass the user's passphrase as-is and this is taken care of by the implementation?










share|improve this question






















  • Im not entirely understanding, what you want to do. you want to create a symmetric encryption using a passphrase of the user, and you will have it on the server side so will be able to use it as a seed in both sides? I'm not following what are you willing to do with these pieces. Are you willing to use a key separation technique or you just want to successfully and securely get a symmetric key?

    – Daniel Vega
    Mar 7 at 15:42






  • 1





    createCipheriv() doesn't modify the user specified key, so yes, if you have a password you should use a KDF.

    – t.m.adam
    Mar 7 at 18:08











  • @DanielVega - no, this is an Electron app and encryption is for data being synchronized

    – millimoose
    Mar 7 at 19:08











  • @t.m.adam Thanks, that’s probably closest to what I’m looking for. Is my intuition that not stretching the passphrase is a Bad Idea correct? (My current thinking is to shove the passphrase and the user ID - both generated using nanoid that claims to produce sound character distributions from a CSPRNG - into Argon2; with only the ID ever existing outside the user’s device as cleartext, the derived key cached on it, the passphrase as close to never as is possible on the platform.)

    – millimoose
    Mar 8 at 18:32






  • 1





    Yes, never use a password as key. Argon2 is a very good KDF, but it's not supported by crypto as far as I know. I'll post an answer using PBKDF2/scrypt if you're interested.

    – t.m.adam
    Mar 8 at 18:45













0












0








0








I need to implement symmetric encryption using a user's passphrase in a NodeJS application. When using crypto.createCipheriv(), do I need to perform some sort of key derivation on the passphrase to obtain a value for the key parameter, or is it sufficient to just pass the user's passphrase as-is and this is taken care of by the implementation?










share|improve this question














I need to implement symmetric encryption using a user's passphrase in a NodeJS application. When using crypto.createCipheriv(), do I need to perform some sort of key derivation on the passphrase to obtain a value for the key parameter, or is it sufficient to just pass the user's passphrase as-is and this is taken care of by the implementation?







javascript node.js encryption






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Mar 5 at 2:07









millimoosemillimoose

32.6k763106




32.6k763106












  • Im not entirely understanding, what you want to do. you want to create a symmetric encryption using a passphrase of the user, and you will have it on the server side so will be able to use it as a seed in both sides? I'm not following what are you willing to do with these pieces. Are you willing to use a key separation technique or you just want to successfully and securely get a symmetric key?

    – Daniel Vega
    Mar 7 at 15:42






  • 1





    createCipheriv() doesn't modify the user specified key, so yes, if you have a password you should use a KDF.

    – t.m.adam
    Mar 7 at 18:08











  • @DanielVega - no, this is an Electron app and encryption is for data being synchronized

    – millimoose
    Mar 7 at 19:08











  • @t.m.adam Thanks, that’s probably closest to what I’m looking for. Is my intuition that not stretching the passphrase is a Bad Idea correct? (My current thinking is to shove the passphrase and the user ID - both generated using nanoid that claims to produce sound character distributions from a CSPRNG - into Argon2; with only the ID ever existing outside the user’s device as cleartext, the derived key cached on it, the passphrase as close to never as is possible on the platform.)

    – millimoose
    Mar 8 at 18:32






  • 1





    Yes, never use a password as key. Argon2 is a very good KDF, but it's not supported by crypto as far as I know. I'll post an answer using PBKDF2/scrypt if you're interested.

    – t.m.adam
    Mar 8 at 18:45

















  • Im not entirely understanding, what you want to do. you want to create a symmetric encryption using a passphrase of the user, and you will have it on the server side so will be able to use it as a seed in both sides? I'm not following what are you willing to do with these pieces. Are you willing to use a key separation technique or you just want to successfully and securely get a symmetric key?

    – Daniel Vega
    Mar 7 at 15:42






  • 1





    createCipheriv() doesn't modify the user specified key, so yes, if you have a password you should use a KDF.

    – t.m.adam
    Mar 7 at 18:08











  • @DanielVega - no, this is an Electron app and encryption is for data being synchronized

    – millimoose
    Mar 7 at 19:08











  • @t.m.adam Thanks, that’s probably closest to what I’m looking for. Is my intuition that not stretching the passphrase is a Bad Idea correct? (My current thinking is to shove the passphrase and the user ID - both generated using nanoid that claims to produce sound character distributions from a CSPRNG - into Argon2; with only the ID ever existing outside the user’s device as cleartext, the derived key cached on it, the passphrase as close to never as is possible on the platform.)

    – millimoose
    Mar 8 at 18:32






  • 1





    Yes, never use a password as key. Argon2 is a very good KDF, but it's not supported by crypto as far as I know. I'll post an answer using PBKDF2/scrypt if you're interested.

    – t.m.adam
    Mar 8 at 18:45
















Im not entirely understanding, what you want to do. you want to create a symmetric encryption using a passphrase of the user, and you will have it on the server side so will be able to use it as a seed in both sides? I'm not following what are you willing to do with these pieces. Are you willing to use a key separation technique or you just want to successfully and securely get a symmetric key?

– Daniel Vega
Mar 7 at 15:42





Im not entirely understanding, what you want to do. you want to create a symmetric encryption using a passphrase of the user, and you will have it on the server side so will be able to use it as a seed in both sides? I'm not following what are you willing to do with these pieces. Are you willing to use a key separation technique or you just want to successfully and securely get a symmetric key?

– Daniel Vega
Mar 7 at 15:42




1




1





createCipheriv() doesn't modify the user specified key, so yes, if you have a password you should use a KDF.

– t.m.adam
Mar 7 at 18:08





createCipheriv() doesn't modify the user specified key, so yes, if you have a password you should use a KDF.

– t.m.adam
Mar 7 at 18:08













@DanielVega - no, this is an Electron app and encryption is for data being synchronized

– millimoose
Mar 7 at 19:08





@DanielVega - no, this is an Electron app and encryption is for data being synchronized

– millimoose
Mar 7 at 19:08













@t.m.adam Thanks, that’s probably closest to what I’m looking for. Is my intuition that not stretching the passphrase is a Bad Idea correct? (My current thinking is to shove the passphrase and the user ID - both generated using nanoid that claims to produce sound character distributions from a CSPRNG - into Argon2; with only the ID ever existing outside the user’s device as cleartext, the derived key cached on it, the passphrase as close to never as is possible on the platform.)

– millimoose
Mar 8 at 18:32





@t.m.adam Thanks, that’s probably closest to what I’m looking for. Is my intuition that not stretching the passphrase is a Bad Idea correct? (My current thinking is to shove the passphrase and the user ID - both generated using nanoid that claims to produce sound character distributions from a CSPRNG - into Argon2; with only the ID ever existing outside the user’s device as cleartext, the derived key cached on it, the passphrase as close to never as is possible on the platform.)

– millimoose
Mar 8 at 18:32




1




1





Yes, never use a password as key. Argon2 is a very good KDF, but it's not supported by crypto as far as I know. I'll post an answer using PBKDF2/scrypt if you're interested.

– t.m.adam
Mar 8 at 18:45





Yes, never use a password as key. Argon2 is a very good KDF, but it's not supported by crypto as far as I know. I'll post an answer using PBKDF2/scrypt if you're interested.

– t.m.adam
Mar 8 at 18:45












2 Answers
2






active

oldest

votes


















2





+100









Passwords should not be used as keys directly, but they can be used to produce a key with a KDF. That is because a key is expected to have a certain size and because passwords are weak - they use only a limited set of bytes and they usually contain words. This makes them vulnerable to both brute-force and dictionary attacks. KDFs not only produce strong keys, but they also introduce a work factor which makes brute-force attacks impractical.



createCipheriv() does not modify the key contents or size. This is not mentioned in the documentation, but following the source code (from createCipheriv: source, to Cipheriv: source, to createCipherWithIV: source, to prepareSecretKey: source) we see that the key is used as it is. So, the key is expected to have the right size and it should have enough complexity.



Crypto provides two password-based KDFs, scrypt and PBKDF2. It would be best to use scrypt because it is very expensive in terms of CPU and memory resources and it can be adjusted for parallel processing, while PBKDF2 only costs CPU resources. Both KDFs require a salt, which should be long and random.



Creating a key with scrypt:



const keySize = 16; // for AES-128
const salt = crypto.randomBytes(16);
const key = crypto.scryptSync('password', salt, keySize);


Creating a key with pbkdf2:



const keySize = 16; // for AES-128
const salt = crypto.randomBytes(16);
const key = crypto.pbkdf2Sync('password', salt, 10000, keySize, 'sha256');


Where 'sha256' is the underlying hash and 10000 is the recommend minimum number of iterations, that determines the work factor. In scrypt the general work factor is an optional parameter with default value 16384 (2^14), and can be set in options['cost'], where we can also set the block size and parallelization. Those values can be increased quite a lot, depending on the OS; each operation should take about 100 ms.



Finally, Argon2 is considered to be a very good KDF and like scrypt it can be adjusted for CPU and memory consumption and parallel processing. Although Argon2 it is not available in crypto, it is provided by other Node.js packages.






share|improve this answer






























    0














    The difficulty of breaking a cipher depends more on the used algorithm than the length of the password. (omitting brut-force attacks)



    The key extension does not increase security, because you still have the same short password at the begining. For your safety, immediately assume that you had a break-in and application code was leaked. That is, all standard and custom algorithms are public.



    And you will have to use the password extension anyway, because most of the algorithms require a secret with a specific length.




    An earlier answer, a little off topic.



    TL;DR: The best way is to process the password into a binary buffer (string).



    The symmetric encryption is precisely based on the fact that having the secret you are able to perform the reverse operation. Symetric mean operations are reversible.



    Your programming language, framework or library does not matter.



    Some differences are at the stage of packaging the encrypted message. You can receive a raw message, or a beautifully formatted message, where you have added IV and content in base64.



    You also have to process the key in the same way. But it's about coding big endian and little endian and character encoding eg: utf-8, latin2



    IV is an additional protection that aims to generate different encrypted messages for the same incoming message and secret. But as it is written in the last paragraph of the section you are targeting:




    They do not have to be secret: IVs are typically just added to
    ciphertext messages unencrypted.




    In summary: you do not need to affect the encryption process itself, and you need to check what data the Electron needs.



    For example my decrypt procedure (in node, data from PHP):



    let crypto = 
    key: Buffer.from('secret in hex', 'hex'),
    cipher: 'aes-128-cbc',
    iv_size: 16

    let bData = Buffer.from(data.replace(/ /g,'+'), 'base64');
    let iv = bData.slice(0, crypto.iv_size);
    let text = bData.slice(crypto.iv_size);
    var decipher = crypt.createDecipheriv(crypto.cipher, crypto.key, iv);
    decipher.setAutoPadding(false);
    var decrypted = decipher.update(text,'hex','hex');
    decrypted += decipher.final('hex');


    For PHP encrypt:




    $data = mcrypt_encrypt($this->_cipher, $this->_key, $data, $this->_mode, $iv);

    // Use base64 encoding to convert to a string
    return base64_encode($iv.$data);

    //where
    array(
    'key'=> urldecode('secret in urlencode'),
    'cipher' => MCRYPT_RIJNDAEL_128,
    'mode' => MCRYPT_MODE_CBC,
    ),


    As you can see, I had to find the encryption algorithms implemented on both platforms, and provide a way to provide an identical key on both platforms.






    share|improve this answer

























    • I’m not sure what this has to do with my question though? I (think I) know roughly how to roundtrip data through a cipher, I was asking if it’s fine from a security standpoint to use the passphrase directly as input to the cipher, or if I should stretch it with a KDF. Clearly either will “work” as in allow for encrypting then decrypting the data correctly for parties that know the passphrase and KDF if applicable; I’m concerned about whether not using a KDF in my code will make it easier for an attacker to decrypt the data.

      – millimoose
      Mar 8 at 18:04











    • i.e. I’m asking about how to correctly produce the “secret” in your example code, something that happens before everything you’re covering. As for my comment you say you’re reacting to, assuming you mean my answer to Daniel Vega, I just cleared up what seemed to be his assumption that when I say “NodeJS”, I mean a server-side application and that a server is storing a user’s passphrase, which would make using symmetric encryption with such a passphrase pointless to begin with. But I’m not doing that.

      – millimoose
      Mar 8 at 18:07











    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54994413%2fis-it-necessary-to-use-key-derivation-when-using-nodes-crypto-module%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2





    +100









    Passwords should not be used as keys directly, but they can be used to produce a key with a KDF. That is because a key is expected to have a certain size and because passwords are weak - they use only a limited set of bytes and they usually contain words. This makes them vulnerable to both brute-force and dictionary attacks. KDFs not only produce strong keys, but they also introduce a work factor which makes brute-force attacks impractical.



    createCipheriv() does not modify the key contents or size. This is not mentioned in the documentation, but following the source code (from createCipheriv: source, to Cipheriv: source, to createCipherWithIV: source, to prepareSecretKey: source) we see that the key is used as it is. So, the key is expected to have the right size and it should have enough complexity.



    Crypto provides two password-based KDFs, scrypt and PBKDF2. It would be best to use scrypt because it is very expensive in terms of CPU and memory resources and it can be adjusted for parallel processing, while PBKDF2 only costs CPU resources. Both KDFs require a salt, which should be long and random.



    Creating a key with scrypt:



    const keySize = 16; // for AES-128
    const salt = crypto.randomBytes(16);
    const key = crypto.scryptSync('password', salt, keySize);


    Creating a key with pbkdf2:



    const keySize = 16; // for AES-128
    const salt = crypto.randomBytes(16);
    const key = crypto.pbkdf2Sync('password', salt, 10000, keySize, 'sha256');


    Where 'sha256' is the underlying hash and 10000 is the recommend minimum number of iterations, that determines the work factor. In scrypt the general work factor is an optional parameter with default value 16384 (2^14), and can be set in options['cost'], where we can also set the block size and parallelization. Those values can be increased quite a lot, depending on the OS; each operation should take about 100 ms.



    Finally, Argon2 is considered to be a very good KDF and like scrypt it can be adjusted for CPU and memory consumption and parallel processing. Although Argon2 it is not available in crypto, it is provided by other Node.js packages.






    share|improve this answer



























      2





      +100









      Passwords should not be used as keys directly, but they can be used to produce a key with a KDF. That is because a key is expected to have a certain size and because passwords are weak - they use only a limited set of bytes and they usually contain words. This makes them vulnerable to both brute-force and dictionary attacks. KDFs not only produce strong keys, but they also introduce a work factor which makes brute-force attacks impractical.



      createCipheriv() does not modify the key contents or size. This is not mentioned in the documentation, but following the source code (from createCipheriv: source, to Cipheriv: source, to createCipherWithIV: source, to prepareSecretKey: source) we see that the key is used as it is. So, the key is expected to have the right size and it should have enough complexity.



      Crypto provides two password-based KDFs, scrypt and PBKDF2. It would be best to use scrypt because it is very expensive in terms of CPU and memory resources and it can be adjusted for parallel processing, while PBKDF2 only costs CPU resources. Both KDFs require a salt, which should be long and random.



      Creating a key with scrypt:



      const keySize = 16; // for AES-128
      const salt = crypto.randomBytes(16);
      const key = crypto.scryptSync('password', salt, keySize);


      Creating a key with pbkdf2:



      const keySize = 16; // for AES-128
      const salt = crypto.randomBytes(16);
      const key = crypto.pbkdf2Sync('password', salt, 10000, keySize, 'sha256');


      Where 'sha256' is the underlying hash and 10000 is the recommend minimum number of iterations, that determines the work factor. In scrypt the general work factor is an optional parameter with default value 16384 (2^14), and can be set in options['cost'], where we can also set the block size and parallelization. Those values can be increased quite a lot, depending on the OS; each operation should take about 100 ms.



      Finally, Argon2 is considered to be a very good KDF and like scrypt it can be adjusted for CPU and memory consumption and parallel processing. Although Argon2 it is not available in crypto, it is provided by other Node.js packages.






      share|improve this answer

























        2





        +100







        2





        +100



        2




        +100





        Passwords should not be used as keys directly, but they can be used to produce a key with a KDF. That is because a key is expected to have a certain size and because passwords are weak - they use only a limited set of bytes and they usually contain words. This makes them vulnerable to both brute-force and dictionary attacks. KDFs not only produce strong keys, but they also introduce a work factor which makes brute-force attacks impractical.



        createCipheriv() does not modify the key contents or size. This is not mentioned in the documentation, but following the source code (from createCipheriv: source, to Cipheriv: source, to createCipherWithIV: source, to prepareSecretKey: source) we see that the key is used as it is. So, the key is expected to have the right size and it should have enough complexity.



        Crypto provides two password-based KDFs, scrypt and PBKDF2. It would be best to use scrypt because it is very expensive in terms of CPU and memory resources and it can be adjusted for parallel processing, while PBKDF2 only costs CPU resources. Both KDFs require a salt, which should be long and random.



        Creating a key with scrypt:



        const keySize = 16; // for AES-128
        const salt = crypto.randomBytes(16);
        const key = crypto.scryptSync('password', salt, keySize);


        Creating a key with pbkdf2:



        const keySize = 16; // for AES-128
        const salt = crypto.randomBytes(16);
        const key = crypto.pbkdf2Sync('password', salt, 10000, keySize, 'sha256');


        Where 'sha256' is the underlying hash and 10000 is the recommend minimum number of iterations, that determines the work factor. In scrypt the general work factor is an optional parameter with default value 16384 (2^14), and can be set in options['cost'], where we can also set the block size and parallelization. Those values can be increased quite a lot, depending on the OS; each operation should take about 100 ms.



        Finally, Argon2 is considered to be a very good KDF and like scrypt it can be adjusted for CPU and memory consumption and parallel processing. Although Argon2 it is not available in crypto, it is provided by other Node.js packages.






        share|improve this answer













        Passwords should not be used as keys directly, but they can be used to produce a key with a KDF. That is because a key is expected to have a certain size and because passwords are weak - they use only a limited set of bytes and they usually contain words. This makes them vulnerable to both brute-force and dictionary attacks. KDFs not only produce strong keys, but they also introduce a work factor which makes brute-force attacks impractical.



        createCipheriv() does not modify the key contents or size. This is not mentioned in the documentation, but following the source code (from createCipheriv: source, to Cipheriv: source, to createCipherWithIV: source, to prepareSecretKey: source) we see that the key is used as it is. So, the key is expected to have the right size and it should have enough complexity.



        Crypto provides two password-based KDFs, scrypt and PBKDF2. It would be best to use scrypt because it is very expensive in terms of CPU and memory resources and it can be adjusted for parallel processing, while PBKDF2 only costs CPU resources. Both KDFs require a salt, which should be long and random.



        Creating a key with scrypt:



        const keySize = 16; // for AES-128
        const salt = crypto.randomBytes(16);
        const key = crypto.scryptSync('password', salt, keySize);


        Creating a key with pbkdf2:



        const keySize = 16; // for AES-128
        const salt = crypto.randomBytes(16);
        const key = crypto.pbkdf2Sync('password', salt, 10000, keySize, 'sha256');


        Where 'sha256' is the underlying hash and 10000 is the recommend minimum number of iterations, that determines the work factor. In scrypt the general work factor is an optional parameter with default value 16384 (2^14), and can be set in options['cost'], where we can also set the block size and parallelization. Those values can be increased quite a lot, depending on the OS; each operation should take about 100 ms.



        Finally, Argon2 is considered to be a very good KDF and like scrypt it can be adjusted for CPU and memory consumption and parallel processing. Although Argon2 it is not available in crypto, it is provided by other Node.js packages.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Mar 10 at 19:37









        t.m.adamt.m.adam

        11.6k31537




        11.6k31537























            0














            The difficulty of breaking a cipher depends more on the used algorithm than the length of the password. (omitting brut-force attacks)



            The key extension does not increase security, because you still have the same short password at the begining. For your safety, immediately assume that you had a break-in and application code was leaked. That is, all standard and custom algorithms are public.



            And you will have to use the password extension anyway, because most of the algorithms require a secret with a specific length.




            An earlier answer, a little off topic.



            TL;DR: The best way is to process the password into a binary buffer (string).



            The symmetric encryption is precisely based on the fact that having the secret you are able to perform the reverse operation. Symetric mean operations are reversible.



            Your programming language, framework or library does not matter.



            Some differences are at the stage of packaging the encrypted message. You can receive a raw message, or a beautifully formatted message, where you have added IV and content in base64.



            You also have to process the key in the same way. But it's about coding big endian and little endian and character encoding eg: utf-8, latin2



            IV is an additional protection that aims to generate different encrypted messages for the same incoming message and secret. But as it is written in the last paragraph of the section you are targeting:




            They do not have to be secret: IVs are typically just added to
            ciphertext messages unencrypted.




            In summary: you do not need to affect the encryption process itself, and you need to check what data the Electron needs.



            For example my decrypt procedure (in node, data from PHP):



            let crypto = 
            key: Buffer.from('secret in hex', 'hex'),
            cipher: 'aes-128-cbc',
            iv_size: 16

            let bData = Buffer.from(data.replace(/ /g,'+'), 'base64');
            let iv = bData.slice(0, crypto.iv_size);
            let text = bData.slice(crypto.iv_size);
            var decipher = crypt.createDecipheriv(crypto.cipher, crypto.key, iv);
            decipher.setAutoPadding(false);
            var decrypted = decipher.update(text,'hex','hex');
            decrypted += decipher.final('hex');


            For PHP encrypt:




            $data = mcrypt_encrypt($this->_cipher, $this->_key, $data, $this->_mode, $iv);

            // Use base64 encoding to convert to a string
            return base64_encode($iv.$data);

            //where
            array(
            'key'=> urldecode('secret in urlencode'),
            'cipher' => MCRYPT_RIJNDAEL_128,
            'mode' => MCRYPT_MODE_CBC,
            ),


            As you can see, I had to find the encryption algorithms implemented on both platforms, and provide a way to provide an identical key on both platforms.






            share|improve this answer

























            • I’m not sure what this has to do with my question though? I (think I) know roughly how to roundtrip data through a cipher, I was asking if it’s fine from a security standpoint to use the passphrase directly as input to the cipher, or if I should stretch it with a KDF. Clearly either will “work” as in allow for encrypting then decrypting the data correctly for parties that know the passphrase and KDF if applicable; I’m concerned about whether not using a KDF in my code will make it easier for an attacker to decrypt the data.

              – millimoose
              Mar 8 at 18:04











            • i.e. I’m asking about how to correctly produce the “secret” in your example code, something that happens before everything you’re covering. As for my comment you say you’re reacting to, assuming you mean my answer to Daniel Vega, I just cleared up what seemed to be his assumption that when I say “NodeJS”, I mean a server-side application and that a server is storing a user’s passphrase, which would make using symmetric encryption with such a passphrase pointless to begin with. But I’m not doing that.

              – millimoose
              Mar 8 at 18:07















            0














            The difficulty of breaking a cipher depends more on the used algorithm than the length of the password. (omitting brut-force attacks)



            The key extension does not increase security, because you still have the same short password at the begining. For your safety, immediately assume that you had a break-in and application code was leaked. That is, all standard and custom algorithms are public.



            And you will have to use the password extension anyway, because most of the algorithms require a secret with a specific length.




            An earlier answer, a little off topic.



            TL;DR: The best way is to process the password into a binary buffer (string).



            The symmetric encryption is precisely based on the fact that having the secret you are able to perform the reverse operation. Symetric mean operations are reversible.



            Your programming language, framework or library does not matter.



            Some differences are at the stage of packaging the encrypted message. You can receive a raw message, or a beautifully formatted message, where you have added IV and content in base64.



            You also have to process the key in the same way. But it's about coding big endian and little endian and character encoding eg: utf-8, latin2



            IV is an additional protection that aims to generate different encrypted messages for the same incoming message and secret. But as it is written in the last paragraph of the section you are targeting:




            They do not have to be secret: IVs are typically just added to
            ciphertext messages unencrypted.




            In summary: you do not need to affect the encryption process itself, and you need to check what data the Electron needs.



            For example my decrypt procedure (in node, data from PHP):



            let crypto = 
            key: Buffer.from('secret in hex', 'hex'),
            cipher: 'aes-128-cbc',
            iv_size: 16

            let bData = Buffer.from(data.replace(/ /g,'+'), 'base64');
            let iv = bData.slice(0, crypto.iv_size);
            let text = bData.slice(crypto.iv_size);
            var decipher = crypt.createDecipheriv(crypto.cipher, crypto.key, iv);
            decipher.setAutoPadding(false);
            var decrypted = decipher.update(text,'hex','hex');
            decrypted += decipher.final('hex');


            For PHP encrypt:




            $data = mcrypt_encrypt($this->_cipher, $this->_key, $data, $this->_mode, $iv);

            // Use base64 encoding to convert to a string
            return base64_encode($iv.$data);

            //where
            array(
            'key'=> urldecode('secret in urlencode'),
            'cipher' => MCRYPT_RIJNDAEL_128,
            'mode' => MCRYPT_MODE_CBC,
            ),


            As you can see, I had to find the encryption algorithms implemented on both platforms, and provide a way to provide an identical key on both platforms.






            share|improve this answer

























            • I’m not sure what this has to do with my question though? I (think I) know roughly how to roundtrip data through a cipher, I was asking if it’s fine from a security standpoint to use the passphrase directly as input to the cipher, or if I should stretch it with a KDF. Clearly either will “work” as in allow for encrypting then decrypting the data correctly for parties that know the passphrase and KDF if applicable; I’m concerned about whether not using a KDF in my code will make it easier for an attacker to decrypt the data.

              – millimoose
              Mar 8 at 18:04











            • i.e. I’m asking about how to correctly produce the “secret” in your example code, something that happens before everything you’re covering. As for my comment you say you’re reacting to, assuming you mean my answer to Daniel Vega, I just cleared up what seemed to be his assumption that when I say “NodeJS”, I mean a server-side application and that a server is storing a user’s passphrase, which would make using symmetric encryption with such a passphrase pointless to begin with. But I’m not doing that.

              – millimoose
              Mar 8 at 18:07













            0












            0








            0







            The difficulty of breaking a cipher depends more on the used algorithm than the length of the password. (omitting brut-force attacks)



            The key extension does not increase security, because you still have the same short password at the begining. For your safety, immediately assume that you had a break-in and application code was leaked. That is, all standard and custom algorithms are public.



            And you will have to use the password extension anyway, because most of the algorithms require a secret with a specific length.




            An earlier answer, a little off topic.



            TL;DR: The best way is to process the password into a binary buffer (string).



            The symmetric encryption is precisely based on the fact that having the secret you are able to perform the reverse operation. Symetric mean operations are reversible.



            Your programming language, framework or library does not matter.



            Some differences are at the stage of packaging the encrypted message. You can receive a raw message, or a beautifully formatted message, where you have added IV and content in base64.



            You also have to process the key in the same way. But it's about coding big endian and little endian and character encoding eg: utf-8, latin2



            IV is an additional protection that aims to generate different encrypted messages for the same incoming message and secret. But as it is written in the last paragraph of the section you are targeting:




            They do not have to be secret: IVs are typically just added to
            ciphertext messages unencrypted.




            In summary: you do not need to affect the encryption process itself, and you need to check what data the Electron needs.



            For example my decrypt procedure (in node, data from PHP):



            let crypto = 
            key: Buffer.from('secret in hex', 'hex'),
            cipher: 'aes-128-cbc',
            iv_size: 16

            let bData = Buffer.from(data.replace(/ /g,'+'), 'base64');
            let iv = bData.slice(0, crypto.iv_size);
            let text = bData.slice(crypto.iv_size);
            var decipher = crypt.createDecipheriv(crypto.cipher, crypto.key, iv);
            decipher.setAutoPadding(false);
            var decrypted = decipher.update(text,'hex','hex');
            decrypted += decipher.final('hex');


            For PHP encrypt:




            $data = mcrypt_encrypt($this->_cipher, $this->_key, $data, $this->_mode, $iv);

            // Use base64 encoding to convert to a string
            return base64_encode($iv.$data);

            //where
            array(
            'key'=> urldecode('secret in urlencode'),
            'cipher' => MCRYPT_RIJNDAEL_128,
            'mode' => MCRYPT_MODE_CBC,
            ),


            As you can see, I had to find the encryption algorithms implemented on both platforms, and provide a way to provide an identical key on both platforms.






            share|improve this answer















            The difficulty of breaking a cipher depends more on the used algorithm than the length of the password. (omitting brut-force attacks)



            The key extension does not increase security, because you still have the same short password at the begining. For your safety, immediately assume that you had a break-in and application code was leaked. That is, all standard and custom algorithms are public.



            And you will have to use the password extension anyway, because most of the algorithms require a secret with a specific length.




            An earlier answer, a little off topic.



            TL;DR: The best way is to process the password into a binary buffer (string).



            The symmetric encryption is precisely based on the fact that having the secret you are able to perform the reverse operation. Symetric mean operations are reversible.



            Your programming language, framework or library does not matter.



            Some differences are at the stage of packaging the encrypted message. You can receive a raw message, or a beautifully formatted message, where you have added IV and content in base64.



            You also have to process the key in the same way. But it's about coding big endian and little endian and character encoding eg: utf-8, latin2



            IV is an additional protection that aims to generate different encrypted messages for the same incoming message and secret. But as it is written in the last paragraph of the section you are targeting:




            They do not have to be secret: IVs are typically just added to
            ciphertext messages unencrypted.




            In summary: you do not need to affect the encryption process itself, and you need to check what data the Electron needs.



            For example my decrypt procedure (in node, data from PHP):



            let crypto = 
            key: Buffer.from('secret in hex', 'hex'),
            cipher: 'aes-128-cbc',
            iv_size: 16

            let bData = Buffer.from(data.replace(/ /g,'+'), 'base64');
            let iv = bData.slice(0, crypto.iv_size);
            let text = bData.slice(crypto.iv_size);
            var decipher = crypt.createDecipheriv(crypto.cipher, crypto.key, iv);
            decipher.setAutoPadding(false);
            var decrypted = decipher.update(text,'hex','hex');
            decrypted += decipher.final('hex');


            For PHP encrypt:




            $data = mcrypt_encrypt($this->_cipher, $this->_key, $data, $this->_mode, $iv);

            // Use base64 encoding to convert to a string
            return base64_encode($iv.$data);

            //where
            array(
            'key'=> urldecode('secret in urlencode'),
            'cipher' => MCRYPT_RIJNDAEL_128,
            'mode' => MCRYPT_MODE_CBC,
            ),


            As you can see, I had to find the encryption algorithms implemented on both platforms, and provide a way to provide an identical key on both platforms.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Mar 8 at 20:22

























            answered Mar 8 at 9:04









            bato3bato3

            1,83811020




            1,83811020












            • I’m not sure what this has to do with my question though? I (think I) know roughly how to roundtrip data through a cipher, I was asking if it’s fine from a security standpoint to use the passphrase directly as input to the cipher, or if I should stretch it with a KDF. Clearly either will “work” as in allow for encrypting then decrypting the data correctly for parties that know the passphrase and KDF if applicable; I’m concerned about whether not using a KDF in my code will make it easier for an attacker to decrypt the data.

              – millimoose
              Mar 8 at 18:04











            • i.e. I’m asking about how to correctly produce the “secret” in your example code, something that happens before everything you’re covering. As for my comment you say you’re reacting to, assuming you mean my answer to Daniel Vega, I just cleared up what seemed to be his assumption that when I say “NodeJS”, I mean a server-side application and that a server is storing a user’s passphrase, which would make using symmetric encryption with such a passphrase pointless to begin with. But I’m not doing that.

              – millimoose
              Mar 8 at 18:07

















            • I’m not sure what this has to do with my question though? I (think I) know roughly how to roundtrip data through a cipher, I was asking if it’s fine from a security standpoint to use the passphrase directly as input to the cipher, or if I should stretch it with a KDF. Clearly either will “work” as in allow for encrypting then decrypting the data correctly for parties that know the passphrase and KDF if applicable; I’m concerned about whether not using a KDF in my code will make it easier for an attacker to decrypt the data.

              – millimoose
              Mar 8 at 18:04











            • i.e. I’m asking about how to correctly produce the “secret” in your example code, something that happens before everything you’re covering. As for my comment you say you’re reacting to, assuming you mean my answer to Daniel Vega, I just cleared up what seemed to be his assumption that when I say “NodeJS”, I mean a server-side application and that a server is storing a user’s passphrase, which would make using symmetric encryption with such a passphrase pointless to begin with. But I’m not doing that.

              – millimoose
              Mar 8 at 18:07
















            I’m not sure what this has to do with my question though? I (think I) know roughly how to roundtrip data through a cipher, I was asking if it’s fine from a security standpoint to use the passphrase directly as input to the cipher, or if I should stretch it with a KDF. Clearly either will “work” as in allow for encrypting then decrypting the data correctly for parties that know the passphrase and KDF if applicable; I’m concerned about whether not using a KDF in my code will make it easier for an attacker to decrypt the data.

            – millimoose
            Mar 8 at 18:04





            I’m not sure what this has to do with my question though? I (think I) know roughly how to roundtrip data through a cipher, I was asking if it’s fine from a security standpoint to use the passphrase directly as input to the cipher, or if I should stretch it with a KDF. Clearly either will “work” as in allow for encrypting then decrypting the data correctly for parties that know the passphrase and KDF if applicable; I’m concerned about whether not using a KDF in my code will make it easier for an attacker to decrypt the data.

            – millimoose
            Mar 8 at 18:04













            i.e. I’m asking about how to correctly produce the “secret” in your example code, something that happens before everything you’re covering. As for my comment you say you’re reacting to, assuming you mean my answer to Daniel Vega, I just cleared up what seemed to be his assumption that when I say “NodeJS”, I mean a server-side application and that a server is storing a user’s passphrase, which would make using symmetric encryption with such a passphrase pointless to begin with. But I’m not doing that.

            – millimoose
            Mar 8 at 18:07





            i.e. I’m asking about how to correctly produce the “secret” in your example code, something that happens before everything you’re covering. As for my comment you say you’re reacting to, assuming you mean my answer to Daniel Vega, I just cleared up what seemed to be his assumption that when I say “NodeJS”, I mean a server-side application and that a server is storing a user’s passphrase, which would make using symmetric encryption with such a passphrase pointless to begin with. But I’m not doing that.

            – millimoose
            Mar 8 at 18:07

















            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54994413%2fis-it-necessary-to-use-key-derivation-when-using-nodes-crypto-module%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Save data to MySQL database using ExtJS and PHP [closed]2019 Community Moderator ElectionHow can I prevent SQL injection in PHP?Which MySQL data type to use for storing boolean valuesPHP: Delete an element from an arrayHow do I connect to a MySQL Database in Python?Should I use the datetime or timestamp data type in MySQL?How to get a list of MySQL user accountsHow Do You Parse and Process HTML/XML in PHP?Reference — What does this symbol mean in PHP?How does PHP 'foreach' actually work?Why shouldn't I use mysql_* functions in PHP?

            Compiling GNU Global with universal-ctags support Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern) Data science time! April 2019 and salary with experience The Ask Question Wizard is Live!Tags for Emacs: Relationship between etags, ebrowse, cscope, GNU Global and exuberant ctagsVim and Ctags tips and trickscscope or ctags why choose one over the other?scons and ctagsctags cannot open option file “.ctags”Adding tag scopes in universal-ctagsShould I use Universal-ctags?Universal ctags on WindowsHow do I install GNU Global with universal ctags support using Homebrew?Universal ctags with emacsHow to highlight ctags generated by Universal Ctags in Vim?

            Add ONERROR event to image from jsp tldHow to add an image to a JPanel?Saving image from PHP URLHTML img scalingCheck if an image is loaded (no errors) with jQueryHow to force an <img> to take up width, even if the image is not loadedHow do I populate hidden form field with a value set in Spring ControllerStyling Raw elements Generated from JSP tagds with Jquery MobileLimit resizing of images with explicitly set width and height attributeserror TLD use in a jsp fileJsp tld files cannot be resolved