I have the following code in C# that is working perfectly. I need to create the same function in php that will return the exact same signed license as C#. I am using phpseclib v1.0.22 and for the life of me, I can’t get the php function to return the same signature for a given License and privatekey. I am not a php programer, so I need some help to figure out the error of my ways.
The working C# code is below:
private string SignLicense(string strLic, string strPrivateKey)
{
// Create instance of RSACryptoServiceProvider and import private key params into it
System.Security.Cryptography.RSACryptoServiceProvider rsaCSP = new System.Security.Cryptography.RSACryptoServiceProvider();
rsaCSP.FromXmlString(strPrivateKey);
RSAParameters rsaPrivateParams; // stores private key
rsaPrivateParams = rsaCSP.ExportParameters(true);
rsaCSP.ImportParameters(rsaPrivateParams);
// Convert the string to a Byte array
byte[] userData = Encoding.UTF8.GetBytes(strLic);
// Setup to sign the userData using SHA1 and RSAPKCS1
AsymmetricSignatureFormatter asf = new RSAPKCS1SignatureFormatter(rsaCSP);
HashAlgorithm algorithm = new SHA1Managed();
asf.SetHashAlgorithm(algorithm.ToString);
// Hash the user userData now
byte[] myhashedData; // a byte array to store hash value
string myhashedDataString;
myhashedData = algorithm.ComputeHash(userData);
myhashedDataString = BitConverter.ToString(myhashedData).Replace("-", string.Empty);
// Sign the Hashed data and convert it back to a string and return it to the caller
byte[] mysignature; // holds signatures
mysignature = asf.CreateSignature(algorithm);
return Convert.ToBase64String(mysignature);
}
My attempt at a php equivalent, which is not working is below:
function SignLicense($strLic, $strPrivateKey) {
// Decode the Install Code
$strReq = base64_decode($strLic);
// Create a new Crypt_RSA object using phpseclib
$rsa = new Crypt_RSA();
// Set the hash to sha1 and the encryption mode to PKCS1
$rsa->SetHash("sha1");
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
//Load the Key file from the stored GCode which is in XML Format
$rsa->loadKey($strPrivateKey, CRYPT_RSA_PRIVATE_FORMAT_XML);
//utf8 Encode the license string now
$userdata = utf8_encode($strLic);
//Sign the stLic now (encrypt it using the loaded Private Key (GCODE))
//$hasheddata = base64_encode($rsa->sign($userdata))
$strSig = $rsa->sign($userdata);
// Add the signature to the license
$strLicKey = str_replace('=', '', base64_encode($strSig));
return $strLicKey;
}
When I pass in the same strLic and strPrivateKey to each of these functions I get totally different signed licenses back. Below are what I get back:
C# SignLicense:
uTlJd3Ce8N1Z2I36FznY8wCtlmmgOtmyv1wdos330Bgk4D6S9GlWl+p+lNKcjamDxyrUrt+jf47wVx777W0zZlie9zufX/UkhMZNxM+ZOkdEU61qltyb122M1GBK6BjzhicwM/BW8aP/ei3DZwMrZuSvqxLxjT/Q4bC73xbpTGUl9KssGLmIxsYm0p3wbxsDM85nnD3yCzRtZYpdW1S5UU4EHXqudLPCSDIJ7DCPDft8k7iRsaKhpiloWax9AD2a5y5Hxhkrq4KH58ZcQ1aYCc+eEbfVnOS822EOY7aTOVH8FmiwXgaLgm5/3XsKayJam0GH4th7MXzcn77OPQOQeQ==
php SignLicense:
0ITgqYxK/clH6VbzP6R+oDdD8bfcKrOeurySCrtHnJmjyCYa4WPnNUw63uhEpcnyQOCJjx7YoNqQeeWwHn6URrTymk3ck8XEQ2w6wGvZtgACfpJ/vCgAhd/MYNDyhauaxKqqY2qTjslbaoBi8Ne0chvrgN4iImA3qETX2kwrI+3DZUSW8Zr78dVv8abRjPc8kjG87TK3Mtxf0joT+2/XMB0Dh6A2xCf2Hoz+P4lMNLR85j2X4xyBlW/Kumg6woAgJUhaeQfPbSuSQPrB9N08v7cCgUnuT+YaAjAC1UdBoDovYQ2bZRFSiZ73+Muejk9/m2uHbv6mAsDdVmgUaky9SQ
They are totally different and I can’t for the life of me figure out why. Can someone help me figure this out.
Thanks!
2
Answers
Nope. PHP is a web scripting language that is used for writing the back-end component of a large number of web applications. It has a focused, well defined job, which it does very well indeed.
C#, on the other hand, is a general purpose language, that was developed as the standard, de facto language of the .NET framework. The scope, reach and abilities of C# are far beyond those of PHP, naturally.
That is not to say PHP is an inferior language, it is just that those two languages come from different domains. This is like comparing oranges and apples.
You should use libsodium (https://www.php.net/manual/en/ref.sodium.php) which is bundled with PHP these days. I would not recommend to use a userland PHP implementation (phpseclib in your case).