- 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 know that the encryption algorithm in the C# source code IS: ECDSA SHA-512
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
session_start();
require 'vendor/autoload.php';
use phpseclib3\Crypt\EC;
use phpseclib3\Crypt\PublicKeyLoader;
use phpseclib3\Crypt\EC\Curves\nistp521;
use phpseclib3\Crypt\Hash;
// Đường dẫn đến tệp crb.xml
$crbFilePath = 'crb.xml';
// Nội dung khóa riêng tư đã mã hóa dưới dạng base64
$encryptedPrivateKeyContent = "MIHBMCQGCiqGSIb3DQEMAQMwFgQQhF07E7HT9E2UWQHhcRpLwgICCAAEgZjGWAViMrjZBoiRvW7oP7FuvQFFKJMqk80kHP94clyome8AUHbEzuwoIyfGrvgApj5g6TEZUoDaIiZylxeM+cfIix5znQRl0hj+HkPDxa6XpR+wXaurQvbRFAypUv6L75ZccJdO8KCDwsDB6O9+yqUlKdfTU5JpQsOx0OT+3q5yk8JrmlBzKCg5R+VWPsHUxTgwHJRcr3kd0w==";
$password = '999999999';
// Giải mã base64
$decodedPrivateKeyContent = base64_decode($encryptedPrivateKeyContent);
// Tạo chuỗi PEM bằng cách thêm header và footer
$privateKeyPem = "-----BEGIN ENCRYPTED PRIVATE KEY-----\n";
$privateKeyPem .= chunk_split(base64_encode($decodedPrivateKeyContent), 64, "\n");
$privateKeyPem .= "-----END ENCRYPTED PRIVATE KEY-----\n";
// Giải mã khóa riêng tư
$privateKey = PublicKeyLoader::load($privateKeyPem, $password);
// Đọc nội dung XML từ file
$dom = new DOMDocument();
$dom->preserveWhiteSpace = false;
$dom->load($crbFilePath);
$dom->formatOutput = true;
// Loại bỏ phần tử "Signature" nếu có
while ($dom->getElementsByTagName('Signature')->length > 0) {
$signatureNode = $dom->getElementsByTagName('Signature')->item(0);
$signatureNode->parentNode->removeChild($signatureNode);
}
// Chuyển đổi DOMDocument thành chuỗi XML với khai báo
$xmlProlog = '<?xml version="1.0" encoding="utf-8"?>';
$dataToSign = $xmlProlog . $dom->saveXML($dom->documentElement);
// Tạo chữ ký
$hash = new Hash('sha512');
$hashData = $hash->hash($dataToSign);
$signature = $privateKey->sign($hashData);
// Chuyển chữ ký thành dạng base64 và thêm vào XML
$signatureBase64 = base64_encode($signature);
$signatureElement = $dom->createElement('Signature', $signatureBase64);
$dom->documentElement->appendChild($signatureElement);
// Lưu nội dung XML đã có chữ ký vào tệp crb.xml
file_put_contents($crbFilePath, $dom->saveXML());
// Mã hóa toàn bộ nội dung của tệp crb.xml thành base64 và lưu vào tệp crb.key
$base64Content = base64_encode(file_get_contents($crbFilePath));
$keyFilePath = 'crb.key';
if (file_put_contents($keyFilePath, $base64Content) === false) {
echo "Lỗi: không thể tạo tệp crb.key";
exit;
}
echo "Chữ ký đã được tạo và lưu vào file: " . $keyFilePath;
?>
- 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>sandrobota@gmail.co</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;
}