Juce RSA implementation


#1

Hi,

I’m looking at using Juce’s RSA implementation for implementing a key-based license system. I however want to integrate it with a web backend that hands out license key files based on email address and key-code. Since my whole server-side infrastructure is built with Java, I’d like to use that to implement the backend. I can’t however find anything that seems compatible with Juce’s RSA implementation. Has anyone done something like this? What is the RSA/Cipher you’ve used?

Thanks,

Geert


#2

I did the same thing with a simple juce command-line exe that the server runs to generate the key.


#3

Thanks for the info Jules, I saw that in an earlier thread indeed. Ideally though I would like to keep it in Java instead of having to compile something to binary. Currently I can very easily migrate servers or bring other ones up since it’s all platform agnostic. As soon as a native executable enters the picture, this becomes much less trivial. Do you remember by any chance what you based your RSA implementation on? Maybe BouncyCastle has something compatible. Worst comes to happens, maybe I can just port your logic, it doesn’t seem very involving.


#4

Java also has a BigInteger class. It isn’t that hard to rewrite the RSAKey class for Java but of course you need to change some parts (mainly string parsing for the keys).


#5

Yes, the string parsing I already have done to get the correct bytes to the javax.crypto classes. Looks like I’ll just go all the way then :slight_smile:


#6

The java.cryptox RSA algorithm is most probably different than the JUCE one (regarding key/data representation).
For de/encryption you only need the constructor from a String, creating a BigInteger from a string the same way JUCE does and applyToValue().

Chris


#7

Great, this only took 10 minutes of time to port. For the future people that might be interested, here’s the Java class:

public class RSAKey {
  private BigInteger part1, part2;

  public RSAKey(String key) {
    if (key.contains(",")) {
      String[] split = key.split(",");
      part1 = new BigInteger(split[0], 16);
      part2 = new BigInteger(split[1], 16);
    }
    else {
      throw new IllegalArgumentException("The string needs to be two hex numbers, comma-separated");
    }
  }

  public BigInteger applyToValue(BigInteger value) {
    if (part1.equals(BigInteger.ZERO) || part2.equals(BigInteger.ZERO) || value.compareTo(BigInteger.ZERO) <= 0) {
      return null;
    }

    BigInteger result = BigInteger.ZERO;

    while (!value.equals(BigInteger.ZERO)) {
      result = result.multiply(part2);

      BigInteger[] div = value.divideAndRemainder(part2);
      value = div[0];
      BigInteger remainder = div[1];

      remainder = remainder.modPow(part1, part2);

      result = result.add(remainder);
    }

    return result;
  }
}

Use like this:

    RSAKey rsa = new RSAKey("JUCEhexRSAkey");
    BigInteger result = rsa.applyToValue(new BigInteger("JUCEencryptedHEXstring", 16));
    System.out.println(new String(result.toByteArray(), "UTF-8"));

#8

I ran into a similar problem, but this time it's about "synchronizing" the RSA implemenation of PHP's  phpseclib with JUCE's approach.


Before I try to re-invent the wheel by adapting the original phpseclib code to JUCE's implementation (both are incompatible), has anybody worked on this issue before? I thought I might ask first ;)


#9

For the record, we finally managed to reproduce's JUCE's RSA algorithm with a standard PHP environment. Find our solution below.
 

Keep in mind that JUCE's RSA implenentation is not super-safe (time attacks, etc). I strongly recommend to not use JUCE's RSA for critical network business. In our case, JUCE's RSA implemenation was sufficient, since we only use RSA for certain parts of our key based, "garden fence" copy protection.


First of all, download phpseclib from http://phpseclib.sourceforge.net/ it's an open source (MIT) and dependency free alternative to openSSL. We use its Math/BigInteger.php class to represent the (really) big ints needed for RSA.

Here's the PHP side encryption/decryption code:

<?php

// from http://phpseclib.sourceforge.net/
include('Math/BigInteger.php');

function applyToValue($x, $key_part1, $key_part2)
{
    $part1 = new Math_BigInteger($key_part1, 16);
    $part2 = new Math_BigInteger($key_part2, 16);

    $zero = new Math_BigInteger();
    $value = new Math_BigInteger(strrev($x), 256);

    $result = new Math_BigInteger();

    while (!$value->equals($zero)) {
        $result = $result->multiply($part2);

        list($value, $remainder) = $value->divide($part2);

        $result = $result->add($remainder->modPow($part1, $part2));
    }

    return strrev($result->toBytes());
}


// generated by RSAKey::createKeyPair()
$PUBLIC_KEY_PART_1 = "5";
$PUBLIC_KEY_PART_2 = "60c838206a7e278ea3af103ce3b602d9de733a99f6d37df6580271996c9fba13";

$PRIVATE_KEY_PART_1 = "3a11bb46a64bb155956909be223a01b52c8bee2841d0caee997204997d4c360d";
$PRIVATE_KEY_PART_2 = "60c838206a7e278ea3af103ce3b602d9de733a99f6d37df6580271996c9fba13";

// secret message
$initial = "There's a rabbit in my hat!";

// encrypt by public key
$encrypted = applyToValue($initial, $PUBLIC_KEY_PART_1, $PUBLIC_KEY_PART_2);

// decrypt by private key
$decrypted = applyToValue($encrypted, $PRIVATE_KEY_PART_1, $PRIVATE_KEY_PART_2);

echo $decrypted."\n";

?>


And just for clarity, here's the JUCE side encryption/decryption:
 


RSAKey public_key("5,60c838206a7e278ea3af103ce3b602d9de733a99f6d37df6580271996c9fba13");
RSAKey private_key("3a11bb46a64bb155956909be223a01b52c8bee2841d0caee997204997d4c360d,60c838206a7e278ea3af103ce3b602d9de733a99f6d37df6580271996c9fba13");
 
String initial = "There's a rabbit in my hat!";
 
BigInteger bi;
bi.loadFromMemoryBlock(MemoryBlock(initial.getCharPointer(), initial.length()));
 
// encrypt
public_key.applyToValue(bi);

 
// decrypt
private_key.applyToValue(bi);
 
String decrypted = bi.toMemoryBlock().toString();


#10

@Jules: Maybe we can add gbevin's JAVA and our PHP example to JUCE's documentation?


#11

Sure, thanks guys, I'll add some notes about that.

Keep in mind that JUCE's RSA implenebtation is not super-safe (time attacks, etc)

I'd take issue with that! Assuming there's no flaw in the actual RSA algorithm itself, then the only weakness could be in the random number that you use to generate the key-pair?

Since the RSA::createKeyPair() method provides a parameter where you can provide your own extra randomness bits, then even if you don't trust the default implementation, you could still use it.. And its default RNG is pretty damned convoluted, involving many samples of tick-resolution counters from different timebases, and a lot of complicated system-dependent interactions between them. Even if someone had the skill and patience to reverse-engineer it, I doubt whether they could reduce the search space enough to make an attack feasible. (And it would be a very determined attacker who'd go to all that trouble when you may not even have used the default RNG!)

Personally, when I've used it to generate keys, I've seeded it with some a couple of extra things like a randomly-typed constant, the number of bytes free on my hard disk, etc, so there must be at least a couple of hundred bits of entropy, even if an attacker knew the time when the key was generated to within a few seconds.

 


#12

Fair enough. Maybe I should have worded the warning differently. ;)


I don't expect the typical cracker to get his hands dirty with encryption anyway. But I doubt that any sort of "bedroom" tested implemenation will be rejected by typical security audits (those you face when working for big IT corps or public authority). These ppl usually have no idea about the technical side, they just fill a long, burocratic check-list. Following PCKS guidelines or other established standards helps alot in this case (not to mention interoperability with other technologies).


But don't get me wrong. I am really happy with JUCE's implementation! It's was perfect for our case and will probabaly be just right for most other scenarios as well.

 

Interesting read: http://happybearsoftware.com/you-are-dangerously-bad-at-cryptography.html :)


#13

Oh yes, I know it'd never pass a corporate paranoia test! Just saying that for normal use by non-corporate folk, there's nothing to be nervous about!