- Hello everyone!
- I’m having trouble converting code from C# to PHP.
- I want the code in php to use the same algorithm as my code in c#.
- The signature in the C# code I created was verified correctly, but the signature created from the php code (I used the same private key) was verified failed.
I have tried using many different libraries in php but still the signature cannot be verified
private void btn_Create_Signature_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(txt_CRB_3_3_x.Text))
{
MessageBox.Show("ID is not entered.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
string crbKeyFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "crb.xml");
string crbxml = File.ReadAllText(crbKeyFilePath);
string textBoxData = txt_CRB_3_3_x.Text; // Data from textbox1
string idTagStart = "<Id>";
string idTagEnd = "</Id>";
int startIndex = crbxml.IndexOf(idTagStart) + idTagStart.Length;
int endIndex = crbxml.IndexOf(idTagEnd);
if (startIndex >= 0 && endIndex >= 0)
{
string updatedCrbxml = crbxml.Substring(0, startIndex) + textBoxData + crbxml.Substring(endIndex);
File.WriteAllText(crbKeyFilePath, updatedCrbxml);
}
else
{
MessageBox.Show("ID tags <Id></Id> not found in the file.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
// Path to the file to store the signature
string signedFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "crb.key");
// Read XML content from the file
XElement xelement = XElement.Load(crbKeyFilePath);
// Display XML content in a message box
MessageBox.Show(xelement.ToString(), "XML Content");
// String containing the encrypted private key and password
string privateKey = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "privateKey.pem");
string fileContent = File.ReadAllText(privateKey);
string string_2 = "999999999";
// Remove header and footer from the PEM string
string base64PrivateKey = ExtractBase64FromPem(fileContent);
// Create or get the Signature element
XElement signatureElement = xelement.Element("Signature") ?? new XElement("Signature");
try
{
if (signatureElement.Parent != null)
{
signatureElement.Remove();
}
// Decrypt the private key
AsymmetricKeyParameter asymmetricKeyParameter = smethod_1(base64PrivateKey, string_2);
// Prepare data for signing
byte[] bytes = Encoding.UTF8.GetBytes(xelement.ToString(SaveOptions.DisableFormatting));
// Initialize the signer with the signature algorithm
string string_0 = "1.2.840.10045.4.3.4"; // Change the algorithm if needed
ISigner signer = SignerUtilities.GetSigner(string_0);
signer.Init(true, asymmetricKeyParameter);
signer.BlockUpdate(bytes, 0, bytes.Length);
// Create the signature
byte[] signature = signer.GenerateSignature();
signatureElement.Value = Convert.ToBase64String(signature);
// Save the signature to a file
string signatureBase64 = Convert.ToBase64String(signature);
File.WriteAllText("signatureCSharp.txt", signatureBase64);
}
catch (Exception ex)
{
MessageBox.Show("An error occurred while creating the signature: " + ex.Message);
return;
}
finally
{
// Add the Signature element to the XML
xelement.Add(signatureElement);
// Convert the XML content to a byte array
byte[] xmlBytes = Encoding.UTF8.GetBytes(xelement.ToString());
// Encode the byte array to Base64 string
string base64EncodedXML = Convert.ToBase64String(xmlBytes);
// Save the Base64 string to a file
File.WriteAllText(signedFilePath, base64EncodedXML);
MessageBox.Show("Signature created and saved to file: " + signedFilePath, "Notification", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
-
- PHP source code and private key :
<?php
session_start();
require_once 'vendor/autoload.php';
use EllipticEC;
use kornrunnerKeccak;
use phpseclib3CryptPublicKeyLoader;
// Path to the crb.xml file
$crbFilePath = 'crb.xml'; // Replace 'path/to/crb.xml' with the actual path
// Encrypted private key content in base64 format
$encryptedPrivateKeyContent = "MIHBMCQGCiqGSIb3DQEMAQMwFgQQhF07E7HT9E2UWQHhcRpLwgICCAAEgZjGWAViMrjZBoiRvW7oP7FuvQFFKJMqk80kHP94clyome8AUHbEzuwoIyfGrvgApj5g6TEZUoDaIiZylxeM+cfIix5znQRl0hj+HkPDxa6XpR+wXaurQvbRFAypUv6L75ZccJdO8KCDwsDB6O9+yqUlKdfTU5JpQsOx0OT+3q5yk8JrmlBzKCg5R+VWPsHUxTgwHJRcr3kd0w==";
// Password to decrypt the private key
$password = '999999999';
// Decode base64
$decodedPrivateKeyContent = base64_decode($encryptedPrivateKeyContent);
// Create a PEM string by adding header and footer
$privateKeyPem = "-----BEGIN ENCRYPTED PRIVATE KEY-----n";
$privateKeyPem .= chunk_split(base64_encode($decodedPrivateKeyContent), 64, "n");
$privateKeyPem .= "-----END ENCRYPTED PRIVATE KEY-----n";
// Decrypt the private key
$privateKey = PublicKeyLoader::load($privateKeyPem, $password);
// Read XML content from file
$xmlContent = file_get_contents($crbFilePath);
$xml = new SimpleXMLElement($xmlContent);
// Update the data inside the <Id> tag
$id = 'Data from textbox1'; // Replace with actual data from textbox1
$xml->Id = $id;
// Prepare data to sign
$dataToSign = $xml->asXML();
// Initialize the Elliptic Curve
// Initialize the Elliptic Curve with p521 curve
$ec = new EC('secp521r1');
// Load the private key from PEM string
$key = $ec->keyFromPrivate($privateKey->toString('P-521'), 'pem');
// Compute SHA-512 hash of the data
$hash = Keccak::hash($dataToSign, 512);
// Sign the hash
$signature = $key->sign($hash);
// Convert the signature to DER format
$derSign = $signature->toDER('hex');
// Add the signature to the XML
$xml->addChild('Signature', $derSign);
// Save the XML back to the file
file_put_contents($crbFilePath, $xml->asXML());
echo "Signature has been added to the XML file.";
?>
- This is the content of the xml file that needs to be signed:
<License>
<Id></Id>
<Type>Standard</Type>
<Customer>
<Name>Alessandro Maciell</Name>
<Email>[email protected]</Email>
</Customer>
<Signature>MEUCIQDPSHurS8VlCXGKKvQrMlKOlvRbg0t5+J3O64XYNawqJQIgXrvJjIk0e7ZFt4Kqhosz4tTBQOJ3H3Z+0xatZ0P7ir4=</Signature>
</License>
- C# source code validates signature :
private void btn_Verify_Signature_Click(object sender, EventArgs e)
{
// Determine the path to the crb.key file in the application's root directory
string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "crb.key");
// Check if the file exists
if (!File.Exists(filePath))
{
Console.WriteLine("File crb.key does not exist.");
return;
}
string string_1 = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnO2SV+sdiMX9OzjcWrsDDlWR7AGfh9fNQgnE2AB/QdEYP0AmAjVPGTORSRlSNF9R6V4rPqSJDZRuEcNqOYmBmA==";
// Read XML content from the crb.key file
XElement xelement = XElement.Load(filePath);
XElement signatureElement = xelement.Element("Signature");
bool flag = false;
if (signatureElement != null)
{
try
{
signatureElement.Remove(); // Temporarily remove the "Signature" element
AsymmetricKeyParameter asymmetricKeyParameter = smethod_3(string_1);
byte[] bytes = Encoding.UTF8.GetBytes(xelement.ToString(SaveOptions.DisableFormatting));
ISigner signer = SignerUtilities.GetSigner(this.string_0);
signer.Init(false, asymmetricKeyParameter);
signer.BlockUpdate(bytes, 0, bytes.Length);
flag = signer.VerifySignature(Convert.FromBase64String(signatureElement.Value));
}
finally
{
xelement.Add(signatureElement); // Add the "Signature" element back
}
}
// Use the flag variable to perform necessary actions after verifying the signature
if (flag)
{
// Valid signature
MessageBox.Show("Valid signature.");
}
else
{
// Invalid signature
MessageBox.Show("Invalid signature.");
}
}
private string ExtractBase64FromPem(string pemContent)
{
var start = "-----BEGIN EC PRIVATE KEY-----";
var end = "-----END EC PRIVATE KEY-----";
var base64 = pemContent
.Replace(start, "")
.Replace(end, "")
.Replace("r", "")
.Replace("n", "")
.Trim();
return base64;
}
New contributor
Mẫu Nguyên is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.