title: Why does Node's crypto module limit keys and IVs to 16 bytes?
body: <p>So I've been writing a simple command-line program for encrypting and decrypting files with Node's built-in <code>crypto</code> module:</p>
  
  <pre><code>        if( deciphered_object.multibase_digest != null ){
              ciphered_object.multibase_digest = deciphered_object.multibase_digest;
              try{
                  iv_buffer = Crypto.randomBytes(32);
                  try{
                      cipher = Crypto.createCipheriv( 'aes-256-ofb', secret_keyobject, iv_buffer );
                      if( cipher != null &amp;&amp; typeof(cipher) === 'object' ){
                          encrypted_buffer = cipher.update( deciphered_object.deciphered_data_buffer );
                          encrypted_buffer += cipher.final();
                          if( encrypted_buffer != null &amp;&amp; Buffer.isBuffer(encrypted_buffer) === true ){
                              try{
                                  ciphered_object.ciphered_data_buffer = Buffer.alloc( (1 + iv_buffer.length + encrypted_buffer.length) );
                                  buffer_offset = ciphered_object.ciphered_data_buffer.writeUInt8( iv_buffer.length, 0 );
                                  buffer_offset += iv_buffer.copy( ciphered_object.ciphered_data_buffer, buffer_offset );
                                  buffer_offset += encrypted_buffer.copy( ciphered_object.ciphered_data_buffer, buffer_offset );
                                  if( buffer_offset === ciphered_object.ciphered_data_buffer.length ){
                                      _return = [0, ciphered_object];
                                  } else{
                                      _return = [-256, 'Error: "buffer_offset" is not equal to "ciphered_object.ciphered_data_buffer.length"'];
                                  }
                              } catch(error){
                                  _return = [-128, Utility.format('Buffer.alloc threw: %s', error)];
                              }
                          } else{
                              _return = [-64, 'Error: "ciphered_buffer" is either null or not a buffer.'];
                          }
                      } else{
                          _return = [-32, 'Error: "cipher" is either null or not an object.'];
                      }
                  } catch(error){
                      _return = [-16, Utility.format('Crypto.createCipheriv threw: %s', error)];
                  }
              } catch(error){
                  _return = [-8, Utility.format('Crypto.randomBytes threw: %s', error)];
              }
          } else{
              _return = [-4, 'Error: "deciphered_object.multibase_digest" is either null or undefined.'];
          }
  </code></pre>
  
  <p>However, as I've discovered through brute-force testing, apparently, createCipheriv only accepts key and IV lengths of exactly 16 bytes; against the 32 bytes for the IV and 4096 bytes for the Scrypt-derived secret key, I initially planned on using:</p>
  
  <pre><code>        password = function_return[1];
          function_return = SaltFile.LoadSaltFile();
          if( function_return[0] === 0 ){
              try{
                  scrypt_buffer = Crypto.scryptSync( password, function_return[1], 4096 );
                  secret_keyobject = Crypto.createSecretKey( scrypt_buffer );
                  if( secret_keyobject != null &amp;&amp; typeof(secret_keyobject) === 'object' ){
                      _return = [0, secret_keyobject];
                  } else{
                      _return = [-32, 'Error: "secret_keyobject" is either null or not an object.'];
                  }
              } catch(error){
                  _return = [-16,Utility.format('Crypto.scryptSync threw: %s', error)];
              }
          } else{
              _return = [function_return[0], 'SaltFile.LoadSaltFile: '+function_return[1]];
          }
  </code></pre>
  
  <p>Worst yet, neither of these size limits are mentioned in the documentation for createCipheriv: <a href="https://nodejs.org/api/crypto.html#crypto_crypto_createcipheriv_algorithm_key_iv_options" rel="nofollow noreferrer">https://nodejs.org/api/crypto.html#crypto_crypto_createcipheriv_algorithm_key_iv_options</a></p>
  
  <p>So, really what I'm wondering is why: Why these arbitrary limits? Why have a crypto suite that forces the use ridiculously-weak keys that any old computer could brute force in a matter of minutes? Why aren't these caveats mentioned in the documentation? 
  This 16-byte key limit seems so absurd to me and it makes the whole <code>crypto</code> module useless. Can this be circumvented by using a different algorithm or something? These limits don't make any sense....</p>
  
  <p>Edit:</p>
  
  <blockquote>
    <p>AES keys are 16, 24 and 32 bytes, which is 128, 192 and 256 bits respectively. The iv is always 16 bytes. That's the AES spec. (@jww)</p>
  </blockquote>
  
  <p>Why are RSA keys commonly 4096 bits (512 bytes) but AES is capped at 32 bytes? Why is a bit entropy of 256 sufficient for AES but not RSA? What makes AES keys less susceptible to brute-force attacks than an RSA key?</p>
  
  <blockquote>
    <p>If you want a 32-byte iv, then you need to switch to Rijndael. (@jww)</p>
  </blockquote>
  
  <p>But I thought AES is Rijndael.</p>
  
  <blockquote>
    <p>A brush-up on basic symmetric cryptography might help you determine why this question doesn't make much sense. (@Luke Joshua Park)</p>
  </blockquote>
  
  <p>Really, not helpful; what reading on "basic symmetric cryptography" should I have done before asking this question? Obviously, I'm no expert, nor did I claim to be one, but, in what I <em>have</em> read about symmetric cryptography, it doesn't make sense that 128 bit key is sufficiently secure for AES but not RSA. If you want me to RTFM that's fine but where's this manual I was supposed to have read before asking this question? I was hoping somebody could explain why a key size of 16 bytes in secure despite that not making much intuitive sense. </p>