1

I am using the node-rsa package to do asymmetric encryption with the RSA function.

Currently, I am generating my public and private keys like so:

generateKeys = function() {
  const key = new NodeRSA({ b: 1024 });
  return {
    public: key.exportKey('public'),
    private: key.exportKey('private'),
  }
}

Is there any possible way to generate a key from a given string? I want to do this so that my users can easily write down their private key, which is important to my project. After all, it is nearly impossible to write down a private key that is 1024 characters long.

I am hoping for something like this:

const key = new NodeRSA({ b: 1024 }, "Secret goes here")

I think this may be possible because the sha256 function can accept any string to hash. I know RSA encryption isn't really a hashing function, so I am not sure if the same effect is possible.

Any help is appreciated!

Jacobjanak
  • 307
  • 1
  • 2
  • 10

1 Answers1

4

It seems that there is a simple way of doing this. There is a package called cryptico that can do the thing.

First install the package:

npm i cryptico

Example

const cryptico = require('cryptico');
const PassPhrase = "The Moon is a Harsh Mistress."; 

// The length of the RSA key, in bits.
const Bits = 1024; 

const RSAkey = cryptico.generateRSAKey(PassPhrase, Bits);

const PublicKeyString = cryptico.publicKeyString(RSAkey); 

A better and complete example can be found here

Update

So, if you need an ASYMMETRIC encryption (As I know that works with a pair of keys which are called publickey and privatekey) you can simply use a pure Node.js implementation.

Example

const { generateKeyPairSync, publicEncrypt, privateDecrypt } = require('crypto');

const PassPhrase = "The Moon is a Harsh Mistress.";

const Bits = 1024;

const encryptWithRSA = (input, publickey) => {
    const buffer = Buffer.from(input, 'utf-8');
    const encrypted = publicEncrypt(publicKey, buffer);
    return encrypted.toString("base64");
}

const decryptWithRSA = function (input, privatekey) {
    const buffer = Buffer.from(input, 'base64');
    const decrypted = privateDecrypt(
        {
            key: privatekey,
            passphrase: PassPhrase,
        },
        buffer,
    )
    return decrypted.toString("utf8");
};

const { privateKey, publicKey } = generateKeyPairSync('rsa', {
    modulusLength: Bits,
    publicKeyEncoding: {
        type: 'spki',
        format: 'pem'
    },
    privateKeyEncoding: {
        type: 'pkcs8',
        format: 'pem',
        cipher: 'aes-256-cbc',
        passphrase: PassPhrase
    }
});

const encrypted = encryptWithRSA('yes i know', publicKey)
console.log(encrypted);

console.log(decryptWithRSA(encrypted, privateKey));

Output (The encrypted value is random as you know)

t3Gw+PlKn84gx2wkj99we345C6ZjIElpgDkzXjio2aWRwI28qTMev14H7o219P6Lw9STGnfK4FgTYO/cvLGlzplqRv6X5AgrstwsGQN88wmKHe5+6cxlpzPFNPWLUqtAvsIOPZe+ghaRGCkOT2ETUp4PiqwOTJ2EtmyVqQHt+f4=
yes i know
Alireza Kiani
  • 410
  • 1
  • 5
  • 11
  • Thank you very much! I'm realizing I left something out of my original question: I am doing ASYMMETRIC encryption. My fault, I should have specified that. Does cryptico support asymmetric encryption? Glancing over the docs, it doesn't look like it but please let me know if it does. – Jacobjanak Apr 12 '21 at 00:26
  • 1
    @Jacobjanak Updated the answer, I think that might fix your problem, the `PassPhrase` variable would do the thing (it's used as `privatekey`'s passphrase) – Alireza Kiani Apr 12 '21 at 06:34
  • Landed here and I find sorta puzzled with a similar problem. I expected a flow like that: user types in some phrase, like 9 (3x3) or 16 (4x4) non-repeating words, and I would use this to produce a binary thingy. for flow like this: `("word1 ... w9")` => `???` => `[binary_form_of_rsa_key,`binary_form_of_public_key`]` => `[createPrivateKey(binary_form_of_rsa_key), createPublicKey(binary_form_of_public_key)` – Kote Isaev Dec 25 '22 at 13:23