Question

I'm trying to implement RSA Encryption in both Java and PHP, but I can't seem to get PHP to recognize my Java public/private keys. Here is the java code to Encode/Decode the Public and Private Keys:

public static byte[] EncodePublicKey(PublicKey _publickey) throws Exception
{
    return _publickey.getEncoded();
}

public static PublicKey DecodePublicKey(byte[] _encodedkey) throws Exception
{
    KeyFactory fac = KeyFactory.getInstance("RSA");
    X509EncodedKeySpec encodedKey = new X509EncodedKeySpec(_encodedkey);
    return fac.generatePublic(encodedKey);
}

public static byte[] EncodePrivateKey(PrivateKey _privatekey) throws Exception
{
    return _privatekey.getEncoded();
}

public static PrivateKey DecodePrivateKey(byte[] _encodedkey) throws Exception
{
    KeyFactory fac = KeyFactory.getInstance("RSA");
    PKCS8EncodedKeySpec encodedKey = new PKCS8EncodedKeySpec(_encodedkey);
    return fac.generatePrivate(encodedKey);
}

I first tried using the PEAR Crypt_RSA functions, but it doesn't support X.509 or PKCS8 (it just simply base64 encodes the serialized modulus, exponent and key type). I then tried the OpenSSL "openssl_get_publickey" function but it doesn't appear to recognize the format either.

Any help would be greatly appreciated o.O

Was it helpful?

Solution

You need to convert the binary format (DER) from Java to PEM for OpenSSL (and the PHP bindings). You can test your Java key files using the OpenSSL command line by specifying the -inform DER option on the command line.

<?
function pem2der($pem_data) {
  $begin = "KEY-----";
  $end   = "-----END";
  $pem_data = substr($pem_data, strpos($pem_data, $begin)+strlen($begin));
  $pem_data = substr($pem_data, 0, strpos($pem_data, $end));
  $der = base64_decode($pem_data);
  return $der;
}

function der2pem($der_data) {
  $pem = chunk_split(base64_encode($der_data), 64, "\n");
  $pem = "-----BEGIN PUBLIC KEY-----\n".$pem."-----END PUBLIC KEY-----\n";
  return $pem;
}

// load the public key from a DER-encoded file
$pubkey = der2pem(file_get_contents("pubkey"));
?>

For more information about using OpenSSL keys in Java, check out this link.

OTHER TIPS

The PHP functions require PEM encoded keys. It's trivial to convert DER encoded keys into PEM.

Here is my code to convert PKCS#8 private key to PEM,

function pkcs8_to_pem($der) {

    static $BEGIN_MARKER = "-----BEGIN PRIVATE KEY-----";
    static $END_MARKER = "-----END PRIVATE KEY-----";

    $value = base64_encode($der);

    $pem = $BEGIN_MARKER . "\n";
    $pem .= chunk_split($value, 64, "\n");
    $pem .= $END_MARKER . "\n";

    return $pem;
}

For public key in X509, replace PRIVATE with PUBLIC in markers.

http://code.google.com/p/simplersalibrary/ is a simple tool, if you want encrypt something in Java and decrypt in PHP or encrypt in java and decrypt in PHP, simplersa can also generate the pem files for PHP.

You can also try to use CastleCrypt, which allows a easy to use RSA Encryption in JAVA AND PHP: https://github.com/wessnerj/CastleCrypt

For the key generation you may want to try it with openssl:

openssl genrsa -out privateKey.pem 2048
openssl pkcs8 -topk8 -nocrypt -in privateKey.pem -outform der -out privateKey.der
openssl rsa -in privateKey.pem -pubout -outform PEM -out publicKey.pem
openssl rsa -in privateKey.pem -pubout -outform DER -out publicKey.der

This commands gives you private and public key in both DER and PEM Format. For JAVA you have to use the .der keys and for PHP the .pem keys.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top