1

I am getting an errors when I used crypto.constants.RSA_NO_PADDING respectively.

node:internal/crypto/cipher:79
    return method(data, format, type, passphrase, buffer, padding, oaepHash,
           ^

Error: error:0200007A:rsa routines::data too small for key size
    at Object.publicEncrypt (node:internal/crypto/cipher:79:12)
    at Object._encryptFile (C:\Users\GB\Documents\projects\customprojects\numericalarrays\pickler\node_modules\hasher-apis\src\hasher.js:260:28)
    at Object.<anonymous> (C:\Users\GB\Documents\projects\customprojects\numericalarrays\pickler\demos\demos.jscertificate.pickle.js:44:49)
    at Module._compile (node:internal/modules/cjs/loader:1149:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1203:10)
    at Module.load (node:internal/modules/cjs/loader:1027:32)
    at Module._load (node:internal/modules/cjs/loader:868:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:23:47 {
  library: 'rsa routines',
  reason: 'data too small for key size',
  code: 'ERR_OSSL_RSA_DATA_TOO_SMALL_FOR_KEY_SIZE'
}

Node.js v18.10.0

I am getting error when I used crypto.constants.RSA_PKCS1_OAEP_PADDING.

node:internal/crypto/cipher:79
    return method(data, format, type, passphrase, buffer, padding, oaepHash,
           ^

Error: error:0200006E:rsa routines::data too large for key size
    at Object.publicEncrypt (node:internal/crypto/cipher:79:12)
    at Object._encryptFile (C:\Users\GB\Documents\projects\customprojects\numericalarrays\pickler\node_modules\hasher-apis\src\hasher.js:260:28)
    at Object.<anonymous> (C:\Users\GB\Documents\projects\customprojects\numericalarrays\pickler\demos\demos.jscertificate.pickle.js:44:49)
    at Module._compile (node:internal/modules/cjs/loader:1149:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1203:10)
    at Module.load (node:internal/modules/cjs/loader:1027:32)
    at Module._load (node:internal/modules/cjs/loader:868:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:23:47 {
  library: 'rsa routines',
  reason: 'data too large for key size',
  code: 'ERR_OSSL_RSA_DATA_TOO_LARGE_FOR_KEY_SIZE'
}

Node.js v18.10.0

This is the encrypt file function

function _encryptFile(remotePath, remoteDestPath, algorithm = "sha256", keyAlgorithm = "rsa", digest = "base64", keyOptions = { modulusLength: 2048 }, options = { modulusLength: 2048 }) {
    const crypto = require('crypto');
    let data = fs.readFileSync(remotePath, { encoding: options.encoding ? options.encoding : "utf-8", flag: "r" });

    algorithm = algorithm || "sha256";
    keyAlgorithm = keyAlgorithm || "rsa";
    digest = digest || "base64";
    keyOptions = keyOptions || { modulusLength: 2048 };
    options = options || { modulusLength: 2048 };

    const { privateKey, publicKey } = _genKeyPair(keyAlgorithm, keyOptions);

    let encrypted = crypto.publicEncrypt({
        key:  publicKey,
        padding: crypto.constants.RSA_PKCS1_PADDING,
        oaepHash: algorithm
    },
        Buffer.from(data)
    ).toString(digest);

    fs.writeFileSync(remoteDestPath, encrypted);
    return {
        privateKey: privateKey,
        publicKey: publicKey,
        encrypted: encrypted
    }
}

This is the deencrypt file function

function _decryptFile(remotePath, remoteDestPath, privateKey, algorithm = "sha256", keyAlgorithm = "rsa", digest = "base64", options = { modulusLength: 2048 }) {
    const crypto = require('crypto');
    let hashdata = fs.readFileSync(remotePath, { encoding: options.encoding ? options.encoding : "utf-8", flag: "r" });

    algorithm = algorithm || "sha256";
    keyAlgorithm = keyAlgorithm || "rsa";
    digest = digest || "base64";
    options = options || { modulusLength: 2048 };

    let decrypted = crypto.privateDecrypt({
        key: privateKey,
        padding: crypto.constants.RSA_PKCS1_PADDING,
        oaepHash: algorithm
    },
        Buffer.from(hashdata, digest)
    );

    fs.writeFileSync(remoteDestPath, decrypted);
    return {
        decrypted: decrypted.toString("utf-8")
    }
}
function _genKeyPair(keyGenType = "rsa", options = { modulusLength: 2048 }) {
    const crypto = require('crypto');
    const { privateKey, publicKey } = crypto.generateKeyPairSync(keyGenType, options);
    return { privateKey, publicKey }
}

This is the encrypt decrpt file usage of the functions function


// Hash P3 File to P3
let { privateKey, publicKey, encrypted } = hash.encrypt(p1, p1, "sha256", "rsa", "base64", { modulusLength: 2048 }, { modulusLength: 2048 });
// let { privateKey, publicKey, encrypted } = hash.encrypt(p3, p1);
console.log("[hasher._fileHash]: File hashed");
console.log(encrypted);


// DeHash P3 File hashed content to P3
let r3 = hash.decrypt(p1, p1, privateKey, "sha256", "rsa", "base64", { modulusLength: 2048 });
// let r3 = hash.decrypt(p1, p1, privateKey);
console.log("[hasher._fileHash]: File dehashed");
console.log(r3);

This is the contents of the file for I do not get data too large for key size`:

1. C
2. C++
3. Java

This is a file containing a collection of interpreted programming languages.
1. Python
2. Nodejs
3. Ruby

This is the contents of the file for I do not get "data too small for key size":

1. C
2. C++
3. Java

I do not get the error when I use "crypto.constants.RSA_PKCS1_PADDING". What is the issue here and how do I get the buffer length right for dynamic use cases?

Gary
  • 2,293
  • 2
  • 25
  • 47
  • 1
    With RSA only a limited amount of data can be encrypted, namely key size minus a space depending on the padding. For PKCS#1 v1.5 padding this is 256-11=244 bytes for a 2048 bits key, for OAEP it depends on the digest, for SHA256: 256-66=190 bytes. RSA without padding is insecure, so this is not an option. For encryption of larger amounts of data, hybrid encryption should be used: The data is encrypted with a symmetric encryption (e.g. AES) and the symmetric key with an asymmetric encryption (e.g. RSA). – Topaco Mar 01 '23 at 09:22
  • @Topaco thank you. that was of real help. what is the max for rsa like algorithms. is there a list of max bytes for all algorithms in crypto.getCiphers and crypto.getHashes? – Gary Mar 01 '23 at 13:12
  • 1
    The value to subtract from the key size is 11 bytes for PKCS#1 v1.5 padding (see [here](https://stackoverflow.com/a/5868456/9014097)) and for OAEP depends on the digest (see [here](https://crypto.stackexchange.com/a/42100) for different digests). – Topaco Mar 01 '23 at 13:23
  • thank you very much. can you add this as an answer? – Gary Mar 01 '23 at 14:17
  • You're welcome. I have put my comments as an answer. – Topaco Mar 01 '23 at 16:01
  • just one more check. these are my keyoptions `{ modulusLength: 2048, publicKeyEncoding: { type: "pkcs1", format: "pem", }, privateKeyEncoding: { type: "pkcs1", format: "pem", } }` I am getting an error when doing file write `writeFileSync("public.pem", publicKey.toString('hex'))` and the err is `data size too large` `library: 'rsa routines', reason: 'data too large for key size', code: 'ERR_OSSL_RSA_DATA_TOO_LARGE_FOR_KEY_SIZE'` – Gary Mar 01 '23 at 18:34
  • 1
    For a more detailed analysis, you would need to create an [MCVE](https://stackoverflow.com/help/minimal-reproducible-example): In particular, remove the file I/O for the test so that the code can use the data directly instead of files. Also complete the code so that it is executable (currently e.g. `_genKeyPair()` is missing). Also post the function calls with all the input data required by the code. With this, the issue should be reproducible on my side. – Topaco Mar 01 '23 at 18:58
  • there was noting much in the genkeypair. but if i use the commented options with `publicKeyEncoding: { type: "pkcs1", format: "pem", }` and try to dump the key to a file the error happens. but the key generated works fine. – Gary Mar 02 '23 at 02:19
  • 1
    I didn't suspect a bug in `_genKeyPair()`, the function is simply required for the code to be executable. In the current code I don't find a key export, so this seems to be a separate problem. Generally the export works, see here: https://www.jdoodle.com/ia/EyT, which is why it is necessary to present a code with which the failure can be reproduced. Regarding the export you should ask a new question, for further questions about the current code please post an executable code as said, so that the problem is reproducible. Thx. – Topaco Mar 02 '23 at 07:03
  • no i tried that. when i did `publickKey.export().toString("hex")`, it gave me an error saying no function called export. second when i tried `publickKey.toString("hex")` it worked and was able to console out and write to a file. i have `publicKeyEncoding: { type: "pkcs1", format: "pem", }` in the creation. – Gary Mar 03 '23 at 11:39
  • 1
    If `publickKey.toString("hex")` really works, then `publickKey` is not a `KeyObject`. However, in your code from the question, `publicKey` is a `KeyObject`, so I don't see the connection. Here you can find a sample code for your two functions without file I/O: https://www.jdoodle.com/ia/ECF. As you can see the code is executable and encryption, decryption and key export work. If you have further questions, please post a corresponding example, with which your problems can be reproduced! – Topaco Mar 03 '23 at 15:08

1 Answers1

1

When encrypting with RSA, you always have to use a padding for security reasons. The length of the message plus padding can be at most as large as the key size (or the modulus in bytes). Since the padding has a minimum length, this results in a maximum message length that is equal to the key size minus the minimum length for the padding.

For PKCS#1 v1.5 padding (RSAES-PKCS1-v1_5) the minimum length of the padding is 11 bytes. A 2048 bit key can therefore encrypt a maximum of 256 - 11 = 244 bytes, see also here.

For OAEP (RSAES-OAEP), the minimum length of the padding depends on the OAEP digest and is 2 * (hLen + 1), where hLen is the output size of the digest in bytes.
For SHA-1 with an output size of 20 bytes, the minimum length of the padding is therefore 42 bytes, for SHA-256 with an output size of 32 bytes it is 66 bytes.
A 2048-bit key can therefore encrypt a maximum of 256 - 42 = 214 bytes for OAEP/SHA-1 and a maximum of 256 - 66 = 190 bytes for OAEP/SHA-256, see also here for a tabular overview of the maximum message length depending on different key sizes and digests.


For larger messages, encryption is usually not done with RSA, but with hybrid encryption, see also here. For this, the data is encrypted with a symmetric algorithm, e.g. AES, and the symmetric key is encrypted with an asymmetric algorithm, e.g. RSA.

Topaco
  • 40,594
  • 4
  • 35
  • 62
  • just one more check. these are my keyoptions `{ modulusLength: 2048, publicKeyEncoding: { type: "pkcs1", format: "pem", }, privateKeyEncoding: { type: "pkcs1", format: "pem", } }` I am getting an error when doing file write `writeFileSync("public.pem", publicKey.toString('hex'))` and the err is `data size too large` `library: 'rsa routines', reason: 'data too large for key size', code: 'ERR_OSSL_RSA_DATA_TOO_LARGE_FOR_KEY_SIZE'` – Gary Mar 01 '23 at 18:36