6

I'm attempting to call RNGCryptoServiceProvider->GetBytes() from PHP via the COM layer. I can get it to connect to the class, but every time I call the method, I get one of two errors (relating to the parameter). I think it has something to due with the fact that GetBytes takes a fixed size byte array by reference. Since PHP doesn't support fixed sized strings, that's where it gets interesting:

Error 1:

$util    = new \DOTNET(
    'mscorlib',
    'System.Security.Cryptography.RNGCryptoServiceProvider'
);
$data = new \Variant(str_repeat(chr(46), $size), VT_UI1 | VT_ARRAY);
$util->GetBytes($data);

Error [0x80070057] The parameter is incorrect

Which is thrown by the ->GetBytes() line.

If I don't use a variant, but just use a plain string, I still get the same error.

However, if I pass in an array like so:

$data = array('');
$util->GetBytes($data);

Parameter 0: Type mismatch.

So I think the variant/string approach is the correct one (as it passes the parameter type check). But I just can't figure out how to get it working.

The C# interface to the method is:

public override void GetBytes(
    byte[] data
)

Thanks

ircmaxell
  • 163,128
  • 34
  • 264
  • 314
  • It may be not the solution you are looking for but why not create a simple windows service that receives whatever you want to send from PHP and then just return the value encoded (do all the processing in C#)? – Gustavo Rubio Apr 02 '14 at 17:53
  • 2
    @GustavoRubio this is for library code. Actually part of a portable PRNG that attempts to produce strong randomness on all platforms. So services or anything other than system calls are not really acceptable (for what I'm doing). Nice idea though... – ircmaxell Apr 02 '14 at 18:01

1 Answers1

3

It has been years since I touched PHP, let alone tried to interop with .net, but what if you create a string padded to your desired length and unpack() it?

$byte_array = unpack('C*', '12345678');
$util->GetBytes($byte_array);

Whelp, wasted an hour or two playing with it to no result. I'd take a look at this:

http://www.sitepoint.com/forums/showthread.php?766246-PHP-and-NET-Secure-RndNum-Generation-using-DOTNET-class

Two reasonable options there - build a simple wrapper of some kind so you can just call a parameterless method, or use something built in and cross-platform.

superstator
  • 3,005
  • 1
  • 33
  • 43
  • Thanks man. I already came across that thread.. I was looking for a Windows solution for when `mcrypt` is disabled. – Samuel Katz Apr 02 '14 at 10:11
  • 1
    From a practical standpoint, yes, using `mcrypt_create_iv` or a custom wrapper object would be useful in a specific application. This question is more for a generic usage, where you can't install a wrapper object (no access) and you can't control if mcrypt is installed or not (also no access)... Since COM is enabled, hopefully there would be a method to do this... – ircmaxell Apr 02 '14 at 18:04
  • here, take the bounty anyways for trying :P – Samuel Katz Apr 03 '14 at 22:09