RSA Keys Not Working With OpenSSL

I have been trying the examples here: RSA: Private/Public keys between Xojo and PHP – Xojo Programming Blog and I’ve also tried the other example from here: Crypto.DEREncodePublicKey findings to generate keys that will work to encrypt data with php using openssl. I am currently working with php 8 but I have also tried 7. I continue to get the same error message from php.

openssl_public_encrypt(): key parameter is not a valid public key

Here is an example of a public key generated with Xojo that is not working.
-----BEGIN PUBLIC KEY-----
MIGHAoGBAJak4ENayO7vmtnAkiqei5Pf6DeyRLIe2i+2N5DXT/iB5lvPaRoaxaWh
mVDJS7C/DifPlT7x2w1G1QP8AbOyqdGTvPkWZwcZH0w9PnONY1dZpTWCIa0sjfQa
KAmAgItcWKoOYrVxw1Ll1qcAGAYG6etyNU1rEehOubXF3RaImAJ5AgER
-----END PUBLIC KEY-----

I know the php code is working because I can get other non Xojo generated keys to encrypt data with it. Has something changed in openssl in some way that the RSA keys generated using Xojo will no longer work with it? Thanks for any advice.

I think you need BEGIN RSA PUBLIC KEY note the RSA in there. And also in the end. Also set the EncodeBase64(…, 72) the first param is the key and second is set to 72 (instead of 74).
That should do it.

You also need to use OAEP padding. I have this function in my library, but I can’t find anywhere that uses false for the third parameter:

public static function RSAEncrypt(string $public_key, string $data, bool $oaep_padding = true) {
	$flags = ($oaep_padding ? OPENSSL_PKCS1_OAEP_PADDING : OPENSSL_PKCS1_PADDING);
	if (@openssl_public_encrypt($data, $result, $public_key, $flags)) {
		return $result;
	} else {
		throw new Exception('Unable to encrypt: ' . openssl_error_string());
	}
}

As @DerkJ said, you need to make sure the key you export from Xojo is properly formatted. I use this function:

Function PEMEncodePublicKey(Key As String) As String
  Var Base64 As String = EncodeBase64(DecodeHex(Key), 0)
  Var Lines() As String = Array("-----BEGIN PUBLIC KEY-----")
  While Base64.Length > 64
    Lines.Add(Base64.Left(64))
    Base64 = Base64.Middle(64)
  Wend
  If Base64.Length > 0 Then
    Lines.Add(Base64)
  End If
  Lines.Add("-----END PUBLIC KEY-----")
  Return String.FromArray(Lines, Encodings.UTF8.Chr(10))
End Function

Here’s even more code for inspiration:

Edit: For the record, I’m not sure why I’m splitting the Base64 manually in PEMEncodePublicKey. Seems like using 64 for the second parameter of EncodeBase64 would be just as good. If only there were some way I could have left a note for myself in this code…

1 Like

Your PEMEncodePublicKey example appears to be working to generate the correct format I needed. Thanks.

In case anyone comes across this post in the future and needs a solution using the older xojo API. This works.

> Function PEMEncodePublicKey(Key As String) As String```
> Dim Base64 As String = EncodeBase64(DecodeHex(Key), 0)
> Dim Lines() As String 
> Lines.Append("-----BEGIN PUBLIC KEY-----")
> While Base64.Len > 64
>   Lines.Append(Base64.Left(63))
>   Base64 = Base64.Mid(64)
> Wend
> If Base64.Len > 0 Then
>   Lines.Append(Base64)
> End If
> Lines.Append("-----END PUBLIC KEY-----")
> 
> dim s as string
> for i as integer = 0 to Lines.Ubound
>   s = s + Lines(i) + Encodings.UTF8.Chr(10)
> next
> 
> return s
> End Function
1 Like