RSAKey in node.js

I’m trying pass messages between a JUCE app and a node.js app, and ideally I want to be able to encrypt or decrypt messages using the same pair of keys.

Has anyone been able to do something like that? I’m looking to use the keys in some way that can be understood by the crypto node.js library, but it seems like juce::RSAKey is structured somewhat differently?

My understanding in cryptography is very basic, so I might be missing something obvious?

I looked at doing something similar in Ruby, but ended up using the Unlocker JUCE example CLI utility and calling it via a shell command.

It would be preferable to have it all done in Ruby. It would be great if someone could come up with equivalent code for the Unlocker in some of the popular server side web frameworks (e.g. PHP, Node.js, Ruby on Rails)

2 Likes

In the past I did a juce::RSAKey implementation in PHP that used phpseclib 1.0.18 under the hood.
It’s fairly old code, use at your own risk.

class RSAKey
{
    /**
     * @return array [0] = public key, [1] = private key */
    public static function createNewPair ($numBits, $description)
    {
        $rsa = new Crypt_RSA();

        $rsa->setPrivateKeyFormat (CRYPT_RSA_PRIVATE_FORMAT_XML);
        $rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_XML);

        $output = $rsa->createKey ($numBits);

        $privateString = $output['privatekey'];

        $privateXml = simplexml_load_string ($privateString);
        libxml_clear_errors();    // prevent accumulation (and excessive memory usage) if the messages are not used

        $m = base64_decode ((string) $privateXml->Modulus);
        $e = base64_decode ((string) $privateXml->Exponent);
        $d = base64_decode ((string) $privateXml->D);

        $publicKey = new RSAKey();
        $publicKey->part1 = new Math_BigInteger ($e, 256);
        $publicKey->part2 = new Math_BigInteger ($m, 256);

        $privateKey = new RSAKey();
        $privateKey->part1 = new Math_BigInteger ($d, 256);
        $privateKey->part2 = $publicKey->part2;

        return array ($publicKey, $privateKey);
    }


    /**
     * Initialise this RSA key from the given string representation obtained by JUCE.
     */
    public function loadFromJuceString ($string)
    {
        list ($key_part1, $key_part2) = explode (',', $string);

        $this->part1 = new Math_BigInteger ($key_part1, 16);
        $this->part2 = new Math_BigInteger ($key_part2, 16);
    }


    /**
     * @return string
     * */
    public function toJuceString () 
    { 
        return ($this->part1->toHex () . ',' . $this->part2->toHex ()); 
    }

    /**
     * Applies this key to the given message
     *
     * @return the encrypted message
     */
    public function applyToValue ($message)
    {
        $result = new Math_BigInteger ();
        $value = new Math_BigInteger (strrev ($message), 256);
        $zero = new Math_BigInteger ();

        while (!$value->equals ($zero))
        {
            $result = $result->multiply ($this->part2);
            list ($value, $remainder) = $value->divide ($this->part2);
            $result = $result->add ($remainder->modPow ($this->part1, $this->part2));
        }
        return strrev ($result->toBytes ());
    }

    private $part1;
    private $part2;
}
1 Like