How to create self-signed certificate using Ed25519 in C# - c#

I have to generate X509 certificates using Ed25519. I know I should use RequestCertificate class from System.Security.Cryptography.X509Certificates namespace but seems that it doesn't support ed25519.
That's my scenario: I have private ed25519 key and basing on it I need to generate self-signed X509 Certificate that will be able to use in mutual TLS.
I don't have any idea how can I do this while using ed25519, because it seems there is not support for this curve. How can I do this?

Create a configuration file for OpenSSL, e.g. openssl-25519.cnf:
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[req_distinguished_name]
C = DE
CN = www.example.com
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = #alt_names
[alt_names]
DNS.1 = www.example.com
DNS.2 = example.com
You can use File.WriteAllText to a temp file to use it during the certificate signing whereas openSsl25519Configuration is a string of the configuration above, where you can interpolate in your dynamic values.
string tempCnfName = Path.GetTempFileName();
File.WriteAllText(tempCnfName, openSsl25519Configuration);
Then use OpenSSL to request a certificate signing request file, using your private key (example.com.key).
openssl req -new -out example.com.csr -key example.com.key -config openssl-25519.cnf
If you already have an existing private key, refer to the file path to the .key file in the process arguments:
string tempCsrName = Path.GetTempFileName();
Process process = new Process() {
StartInfo = {
FileName = "openssl.exe",
Arguments = $"req -new -out {tempCsrName} -key example.com.key -config {tempCnfName}"
}
};
process.Start();
process.WaitForExit();
And now you can use OpenSSL again to self-sign example.com.csr:
openssl x509 -req -days 700 -in example.com.csr -signkey example.com.key -out example.com.crt
string tempCrtName = Path.GetTempFileName();
Process process = new Process() {
StartInfo = {
FileName = "openssl.exe",
Arguments = $"req x509 -req -days 700 -in {tempCsrName} -signkey example.com.key -out {tempCrtName}"
}
};
process.Start();
process.WaitForExit();
And now you have a self-signed ED25519 certificate that you can move or read as you need through tempCrtName.
If you don't already have a private key, you can generate one:
openssl genpkey -algorithm ED25519 > example.com.key
Source: https://blog.pinterjann.is/ed25519-certificates.html

Related

HttpClient - The message received was unexpected or badly formatted

I am trying to connect to an API that requires two way SSL configured. I have the the certificate and the private key which I configured in postman as shown in the below image.
This works fine in Postman, but SSL fails when I try to implement it in C# using HttpClient. The error that I get is "The message received was unexpected or badly formatted.". I believe it has something to do with incorrect configuration.
I have referred this StackOverflow post to implement my code: Associate a private key with the X509Certificate2 class in .net
Below is what I have tried:
byte[] publicCertificateBytes = File.ReadAllBytes("<Public Certificate>");
var publicCertificate = new X509Certificate2(publicCertificateBytes);
byte[] privateKey = Convert.FromBase64String(File.ReadAllText("<private key file>").Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", ""));
using (var rsa = RSA.Create())
{
rsa.ImportPkcs8PrivateKey(privateKey, out _);
publicCertificate = publicCertificate.CopyWithPrivateKey(rsa);
publicCertificate = new X509Certificate2(publicCertificate.Export(X509ContentType.Pkcs12));
}
var httpService = new GenericUtilityManager().ResolveUtility<IHttpService>();
var handler = new HttpClientHandler();
handler.SslProtocols = SslProtocols.Tls12;
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ClientCertificates.Add(publicCertificate);
handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true;
httpService.InitializeHttpClientHandler(handler);
Please help.
Try to load the certicate using the CreateFromPem static function, this method returns a new certificate with the private key.
var certificateCrt = File.ReadAllText("<Public Certificate>");
var privateKey = File.ReadAllText("<private key file>");
using var certificate = X509Certificate2.CreateFromPem(certificateCrt, privateKey);
If that doesn't work, try to creating a .pfx certificate using OpenSSL:
openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt
I had this problem when I needed to use a certificate on a Windows OS, to work I had to create a .pfx certificate, but on other OS like Mac and Linux it worked fine without a .pfx certificate.

Keyset does not exist although the PrivateKey is set

I'm trying to sign a message using CmsSigner and attaching X509 certificate:
public static byte[] Sign(X509Certificate2 certificate, string keyXml)
{
ContentInfo contentInfo = new ContentInfo(new Oid("1.2.840.113549.1.7.1"), Encoding.ASCII.GetBytes("hello"));
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(keyXml);
using (certificate.GetRSAPrivateKey())
{
certificate.PrivateKey = rsa;
}
var signer = new CmsSigner(certificate);
signer.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1");
signer.SignedAttributes.Add(new Pkcs9SigningTime());
var signedCms = new SignedCms(contentInfo, false);
signedCms.ComputeSignature(signer);
var encodeByteBlock = signedCms.Encode();
return encodeByteBlock;
}
the certificate doesn't have a key (HasPrivateKey is false) so I set it with the right key generated using OpenSSL:
openssl req -new -sha256 -x509 -days 7300 -out ca.crt -keyout ca.key.pem -nodes
I convert the ca.key.pem to XML.
But when ComputeSignature is called, this exception is thrown:
System.Security.Cryptography.CryptographicException: 'Keyset does not
exist'
Stack trace:
at
System.Security.Cryptography.Pkcs.PkcsUtils.CreateSignerEncodeInfo(CmsSigner
signer, Boolean silent, SafeCryptProvHandle& hProv) at
System.Security.Cryptography.Pkcs.SignedCms.Sign(CmsSigner signer,
Boolean silent) at
System.Security.Cryptography.Pkcs.SignedCms.ComputeSignature(CmsSigner
signer, Boolean silent) at
System.Security.Cryptography.Pkcs.SignedCms.ComputeSignature(CmsSigner
signer) at ConsoleTest472.Program.Sign(X509Certificate2
certificate, String keyXml) in
D:\me\Projects\ConsoleTest472\ConsoleTest472\Program.cs:line 56 at
ConsoleTest472.Program.Main(String[] args) in
D:\me\Projects\ConsoleTest472\ConsoleTest472\Program.cs:line 63
What is wrong with the code I'm using? doesn't the keyset is set when the private key is..set?
What is wrong with the code I'm using?
using (certificate.GetRSAPrivateKey())
{
certificate.PrivateKey = rsa;
}
doesn't make much sense. You're acquiring the private key, then ignoring it, attempting to replace it, then disposing it.
A better version would be
var signedCms = new SignedCms(contentInfo, false);
using (X509Certificate2 certWithKey = certificate.CopyWithPrivateKey(rsa))
{
var signer = new CmsSigner(certWithKey);
signer.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1");
signer.SignedAttributes.Add(new Pkcs9SigningTime());
signedCms.ComputeSignature(signer);
}
var encodeByteBlock = signedCms.Encode();
return encodeByteBlock;
Which does the work of binding the private key to a copy of the certificate (rather than do mutation), and does whatever is necessary to make that work (in this case, it'll end up replacing the RSACryptoServiceProvider key with an RSACng key, because the platform only supports CNG for memory-only (ephemeral) keys).
The private key must be either:
in the MY Key Store of the user executing the code
in the MY Key Store of the Machine, with permission granted to the user
stored together with the certificate in a PFX/PKCS#12 file and loaded as X509Certificate2 with the password protecting it.

C# signature verification using ECDSA with SHA256 certificate

I'm trying to use C# and the built in Crypto libraries to verify a signature created using an EC key + SHA256. Here's what I'm doing.
I've created a private key and corresponding certificate using openssl:
$ openssl ecparam -genkey -name prime256v1 -out ca.key
$ openssl req -x509 -new -SHA256 -nodes -key ca.key -days 36500 -out ca.crt
Here are the keys I'm using (don't worry, they're not important):
$ cat ca.key
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIHd3OvRV1nEnoDxGzzemX1x8l2rHasWH3L/LflUGg5vloAoGCCqGSM49
AwEHoUQDQgAE7f1xwQL5m/UcN4zL+zsly6V1g3/wNcL5TdCfWt0XfnUfg0x+RsIf
1uerBnhrmhH0cN9o0xfXg5B3hURFlXVuEQ==
-----END EC PRIVATE KEY-----
$ cat ca.crt
-----BEGIN CERTIFICATE-----
MIIB4TCCAYegAwIBAgIUKt0WdaKI2eRXBO2nVk+OF6AZqHMwCgYIKoZIzj0EAwIw
RTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu
dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAgFw0yMDA1MDcxMzM2MTNaGA8yMTIwMDQx
MzEzMzYxM1owRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAf
BgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDBZMBMGByqGSM49AgEGCCqG
SM49AwEHA0IABO39ccEC+Zv1HDeMy/s7JculdYN/8DXC+U3Qn1rdF351H4NMfkbC
H9bnqwZ4a5oR9HDfaNMX14OQd4VERZV1bhGjUzBRMB0GA1UdDgQWBBRGuUmsyB2h
JCXMRTVMRTcdoWZQaDAfBgNVHSMEGDAWgBRGuUmsyB2hJCXMRTVMRTcdoWZQaDAP
BgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIGG8tQZlh7aJaI34Y7jq
44SmSc/ule9MgjIX+Gg+i5vwAiEA9Jb/304KO4t9OMqFMQeWZXIHdzhDFBwx7FWz
78+UsnY=
-----END CERTIFICATE-----
I then have a simple data file containing the string "Hello". I then sign that file using openssl as follows:
$ openssl dgst -sha256 -sign ca.key data.txt > sig
$ base64 sig
MEUCIQD5593C/NBhHA1DILT72gjhGj/lKjom9vYP+JbuypBrxQIgNAjYT1LihEpPbUhe1n9ccUHQ
vw676bGqOTEU/25qcRQ=
I can then verify the signature by first extracting the public key from the certificate and then using that to verify:
$ openssl x509 -pubkey -noout -in ca.crt > ca.pub
$ cat ca.pub
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7f1xwQL5m/UcN4zL+zsly6V1g3/w
NcL5TdCfWt0XfnUfg0x+RsIf1uerBnhrmhH0cN9o0xfXg5B3hURFlXVuEQ==
-----END PUBLIC KEY-----
$ openssl dgst -verify ca.pub -sha256 -signature sig data.txt
Verified OK
I then try and use C# (.NET Core 3.1) to verify the signature. The code is as follows:
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
namespace security_sandbox
{
class Program
{
static void Main(string[] args)
{
var certData = Encoding.ASCII.GetBytes(
#"-----BEGIN CERTIFICATE-----
MIIB4TCCAYegAwIBAgIUKt0WdaKI2eRXBO2nVk+OF6AZqHMwCgYIKoZIzj0EAwIw
RTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu
dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAgFw0yMDA1MDcxMzM2MTNaGA8yMTIwMDQx
MzEzMzYxM1owRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAf
BgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDBZMBMGByqGSM49AgEGCCqG
SM49AwEHA0IABO39ccEC+Zv1HDeMy/s7JculdYN/8DXC+U3Qn1rdF351H4NMfkbC
H9bnqwZ4a5oR9HDfaNMX14OQd4VERZV1bhGjUzBRMB0GA1UdDgQWBBRGuUmsyB2h
JCXMRTVMRTcdoWZQaDAfBgNVHSMEGDAWgBRGuUmsyB2hJCXMRTVMRTcdoWZQaDAP
BgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIGG8tQZlh7aJaI34Y7jq
44SmSc/ule9MgjIX+Gg+i5vwAiEA9Jb/304KO4t9OMqFMQeWZXIHdzhDFBwx7FWz
78+UsnY=
-----END CERTIFICATE-----");
var cert = new X509Certificate2(certData);
var ecdsa = cert.GetECDsaPublicKey();
var data = Encoding.ASCII.GetBytes("Hello");
var signature = Convert.FromBase64String("MEUCIQD5593C/NBhHA1DILT72gjhGj/lKjom9vYP+JbuypBrxQIgNAjYT1LihEpPbUhe1n9ccUHQvw676bGqOTEU/25qcRQ=");
var success = ecdsa.VerifyData(data, signature, HashAlgorithmName.SHA256);
if (success)
{
Console.WriteLine("Verified");
} else
{
Console.WriteLine("Failed");
}
}
}
}
Unfortunately, it always fails the verification. Where is the mistake?
The lack of PEM/OpenSSL-compatible manipulation tools in .NET proved to be extremely frustrating. I ended up using Bouncy Castle to load the certificate or public key and then use that to verify my ASN signature. Here's a full working code sample demonstrating how to perform the signature verification using both the certificate and the PEM public key and working with an ASN-encoded signature.
using System;
using System.IO;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
namespace security_sandbox
{
class Program
{
static void Main(string[] args)
{
var certificateString = #"-----BEGIN CERTIFICATE-----
MIIB4TCCAYegAwIBAgIUKt0WdaKI2eRXBO2nVk+OF6AZqHMwCgYIKoZIzj0EAwIw
RTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu
dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAgFw0yMDA1MDcxMzM2MTNaGA8yMTIwMDQx
MzEzMzYxM1owRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAf
BgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDBZMBMGByqGSM49AgEGCCqG
SM49AwEHA0IABO39ccEC+Zv1HDeMy/s7JculdYN/8DXC+U3Qn1rdF351H4NMfkbC
H9bnqwZ4a5oR9HDfaNMX14OQd4VERZV1bhGjUzBRMB0GA1UdDgQWBBRGuUmsyB2h
JCXMRTVMRTcdoWZQaDAfBgNVHSMEGDAWgBRGuUmsyB2hJCXMRTVMRTcdoWZQaDAP
BgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIGG8tQZlh7aJaI34Y7jq
44SmSc/ule9MgjIX+Gg+i5vwAiEA9Jb/304KO4t9OMqFMQeWZXIHdzhDFBwx7FWz
78+UsnY=
-----END CERTIFICATE-----";
var pemreader = new PemReader(new StringReader(certificateString));
var cert = (X509Certificate)pemreader.ReadObject();
// Alternatively, load the public key directly
var pubkeyString =
#"-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7f1xwQL5m/UcN4zL+zsly6V1g3/w
NcL5TdCfWt0XfnUfg0x+RsIf1uerBnhrmhH0cN9o0xfXg5B3hURFlXVuEQ==
-----END PUBLIC KEY-----";
pemreader = new PemReader(new StringReader(pubkeyString));
var pubkey = (AsymmetricKeyParameter)pemreader.ReadObject();
var data = "Hello";
var signature = Convert.FromBase64String("MEUCIQD5593C/NBhHA1DILT72gjhGj/lKjom9vYP+JbuypBrxQIgNAjYT1LihEpPbUhe1n9ccUHQvw676bGqOTEU/25qcRQ=");
// Verify using the public key
var signer = SignerUtilities.GetSigner("SHA-256withECDSA");
signer.Init(false, pubkey);
signer.BlockUpdate(Encoding.ASCII.GetBytes(data), 0, data.Length);
var success = signer.VerifySignature(signature);
if (success) {
Console.WriteLine("Signature verified successfully using public key");
} else {
Console.WriteLine("Failed to verify signature using public key");
}
// Verify using the certificate - the certificate's public key is extracted using the GetPublicKey method.
signer.Init(false, cert.GetPublicKey());
signer.BlockUpdate(Encoding.ASCII.GetBytes(data), 0, data.Length);
success = signer.VerifySignature(signature);
if (success) {
Console.WriteLine("Signature verified successfully using certificate");
} else {
Console.WriteLine("Failed to verify signature using certificate");
}
}
}
}

Cryptography: Why am I getting different RSA signatures depending on which certificate store the certificate was loaded from?

I have some working code which produces a correct signature of a string if I load a certificate from a file or from the current user's store. However, if I load the exact same certificate (same .p12 and same thumbprint) from the Machine certificate store, it behaves differently. When loaded from that store, the signatures generated by my C# code are half the length (1024 bits instead of 2048) and are incorrect. The private key appears to be loading properly in both cases.
Why does which store the certificate is loaded from make any difference to which signature is generated? And why would the signature be half the length?
Loaded from CurrentUser:
Thumbprint: FBBE05A1C5F2AEF637CDE20A7985CD1011861651
Has private key:True
rsa.KeySize (bits) =2048
Signature Length (bits): 2048
Signature: kBC2yh0WCo/AU8aVo+VUbRoh67aIJ7SWM4dRMkNvt...
(correct)
Loaded from LocalMachine:
Thumbprint: FBBE05A1C5F2AEF637CDE20A7985CD1011861651
Has private key: True
rsa.KeySize (bits) = 1024
Signature Length (bits): 1024
Signature: RijmdQ73DXHK1IUYkOzov2R+WRdHW8tLqsH....
(incorrect - and note the 1024 bit key size and signature length)
Here's the C# I'm using:
string s = "AE0DE01564,1484821101811,http://localhost:8080/example_site/CallBack";
var inputData = Encoding.UTF8.GetBytes(s);
var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
string thumbprint = CleanThumbPrint("fb be 05 a1 c5 f2 ae f6 37 cd e2 0a 79 85 cd 10 11 86 16 51");
X509Certificate2Collection col = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
// TODO: close store.
X509Certificate2 certificate = null;
Console.WriteLine("Cert count: " + col.Count);
if (col.Count == 1)
{
certificate = col[0];
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)col[0].PrivateKey;
// Force use of the Enhanced RSA and AES Cryptographic Provider with openssl-generated SHA256 keys
var enhCsp = new RSACryptoServiceProvider().CspKeyContainerInfo;
var cspparams = new CspParameters(enhCsp.ProviderType, enhCsp.ProviderName, rsa.CspKeyContainerInfo.KeyContainerName);
rsa = new RSACryptoServiceProvider( cspparams);
Console.WriteLine("Name: " + certificate.SubjectName.Name);
Console.WriteLine("Thumbprint: " + certificate.Thumbprint);
Console.WriteLine("Has private key: " + certificate.HasPrivateKey);
Console.WriteLine("Sig algorithm: " + certificate.SignatureAlgorithm);
Console.WriteLine("rsa.KeySize (bits) =" + rsa.KeySize);
var sha256 = CryptoConfig.CreateFromName("SHA256");
byte[] signature = rsa.SignData(inputData, sha256);
Console.WriteLine("Signature Length (bits): " + signature.Length * 8);
Console.WriteLine("Signature: " + System.Convert.ToBase64String(signature));
Console.WriteLine();
}
It turns out it was something to do with the file format of the certificate I was using which I created with OpenSSL and the fact that the crypto provider wasn't set. The critical command is number 5 below:
Here are the commands I used to create the working certificate:
Generate a keypair:
openssl genrsa -out private_key.pem 2048
Extract the public key:
openssl rsa -pubout -in private_key.pem -out public_key.pem
Create a CSR Certificate Signing Request from private key:
openssl req -new -key private_key.pem -out csr.csr
Generate a self signed certificate:
openssl x509 -req -days 1095 -in csr.csr -signkey private_key.pem -out certificate.crt
Create a PFX format certificate with the specified CSP:
openssl pkcs12 -export -in certificate.crt -inkey private_key.pem -CSP "Microsoft Enhanced RSA and AES Cryptographic Provider" -out TEST_pfx.pfx

PHP validate client signature using client public key

Hi I'm building REST service and planning to erase language restriction for developing both client and server from this project, the REST server currently written using PHP.
For security I'm validating their hash code, and also their client app signature. Currently the hash is successful but for the signature it always failed.
Every client will have their own private key and on the server we will have their public key to verify the signature, each request to server will send a signature.
If the client is a web server there will be only one private key for all user. If the client is a native app ( C# ) then each installed client app will have their unique private key.
PHP client to PHP REST server -> calculate hash ok, verify client signature ok
C# client (winapp) to PHP REST Server -> calculate hash ok, verify client signature failed
In the future I want to try with JAVA and vice versa.
I use easy way to create a self sign certificate
openssl genrsa -des3 -out netclient.key 2048
openssl req -new -x509 -key netclient.key -out netclient.crt
openssl pkcs12 -export -inkey netclient.key -in netclient.crt -out netclient.p12
Here is my code to sign data using C#
public static string (string Base64EncryptedData ) {
X509Certificate2 my;
my = new X509Certificate2("cert/netclient.p12", "abcdefg", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
RSACryptoServiceProvider csp = null;
csp = (RSACryptoServiceProvider)my.PrivateKey;
SHA1Managed sha1 = new SHA1Managed();
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] data = encoding.GetBytes(Base64EncryptedData);
byte[] hash = sha1.ComputeHash(data);
return Convert.ToBase64String(csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA1")));
}
It return a signature (base64) which I send to PHP REST server using GET method.
On PHP Server I recount the hash and verify but it never return 1. Currently I copy manually all the key to the server.
set_include_path(get_include_path() . PATH_SEPARATOR ."lib");
include("Crypt/RSA.php");
$p12cert = array();
$fp=fopen("cert/netclient.p12","r");
$priv_key=fread($fp,8192);
fclose($fp);
openssl_pkcs12_read($priv_key, $p12cert, "abcdefg");
//try using the phpseclib library from http://phpseclib.sourceforge.net
//req() will get all the $_POST, $_GET data req("signature") = $_GET["signature"];
//$hash_request is an base64_encode string same exact value as the one in C#
$rsa = new Crypt_RSA();
$rsa->setHash("sha1");
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$rsa->loadKey($p12cert["cert"]);
$verified_phpseclib = $rsa->verify($hash_request, base64_decode(req("signature"))) ? "verified" : "diff";
//try using php built in openssl
$verified_builtin = openssl_verify($hash_request, base64_decode(req('signature')), $p12cert["cert");
Non of the result return "verified" or "1"
Could it be because when C# sign the data, the format of the data is byte[] ?
Or is there other reason ?
I'm running all the code in linux
php - using apache2
c# - using monodevelop
Here is my pk12 array after reading using openssl_pkcs12_read you can download it here
Array
(
[cert] => -----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJANjuyBraeAN0MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTMwMzE5MDA0ODI0WhcNMTMwNDE4MDA0ODI0WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAojE1Md/DET9mvKpoNJvb+mbGdTfSYuXQurGxb5pU0ba+gVeARbc8fjaK
D/2EKhUP/7240a31e5qI/2UlgiHO+ghQKDPo+5W5CetDVR1oMbWVA1fp7/gv8DEV
AvNV9nVkYzxnoVPs+W0MhMlWPrhCNSqQ28BbbL0EzXwXESnMw0I2VAhGWDNG0zSl
U03l5zh8jzzRKKK+gw4gIKo0u4lEUqB52MaXPzdwQkOEXRUdT+l1vK3DGfQycMrm
gZEN6IXDvpSFcQfHJlICK06+JNgDM0tYbif2mMfDEPKeFIjGC8S2ZDTZlR92LCk1
/WUGhdDFobbLAOx40M/etOcaEN1bgQIDAQABo1AwTjAdBgNVHQ4EFgQUTr0r49JA
DUKKiIQkRVlog4T952AwHwYDVR0jBBgwFoAUTr0r49JADUKKiIQkRVlog4T952Aw
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAO2IwjeIEVy8aLCOTjCkt
fTyLYuoiex+Xa/Dy2Xdl51Q44uAjCeSVsm1mXko+cZSypngGDu8W97sifzeR+pmW
7r6r+Rj+5pZcQiLQOCUQrXVpqHeiCS8QpOhpxGF+TOLy1O9zcqQwEiohKmzJB++d
1NM8//OBx1/Nyu7eLTKrTqfBdhuXfee963HVF9uBxwV8oa3UTQfhKu2vwJ64pcbU
5OVQw4rfhfSYhB1uu+zMQhCZ3hsroj2rC6Kfb8t3BNzngQwiqDBprmJznmJY38pW
kw0NIx+GrO1NUu+Ydl/7MXChujQajqSkG65Z9iJ8G7eegrY988INPVIfitIopWF+
jg==
-----END CERTIFICATE-----
[pkey] => -----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCiMTUx38MRP2a8
qmg0m9v6ZsZ1N9Ji5dC6sbFvmlTRtr6BV4BFtzx+NooP/YQqFQ//vbjRrfV7moj/
ZSWCIc76CFAoM+j7lbkJ60NVHWgxtZUDV+nv+C/wMRUC81X2dWRjPGehU+z5bQyE
yVY+uEI1KpDbwFtsvQTNfBcRKczDQjZUCEZYM0bTNKVTTeXnOHyPPNEoor6DDiAg
qjS7iURSoHnYxpc/N3BCQ4RdFR1P6XW8rcMZ9DJwyuaBkQ3ohcO+lIVxB8cmUgIr
Tr4k2AMzS1huJ/aYx8MQ8p4UiMYLxLZkNNmVH3YsKTX9ZQaF0MWhtssA7HjQz960
5xoQ3VuBAgMBAAECggEAB/TgBi1S9XKlyJWXfRU0SmlmTPPLF1zsy2vSJ4ZrqMoN
OG0hdsoRZqOoTDaEmEfmPAaDnY2qIEEpfVXp7CNacvubaw143Xav2CO5buB9bwrY
X4ydhk8nkuHlhPqI+gkyPogFEW37jxTha1YxK+yAGvmWl6EtGv1+0dHHk+j4CZAO
9DH1gZRBOXyeAJAhYuBMxxKfZhBNgGHzLtf9SGoOd2v9ya/h4CuqYh/CoxHGM/w1
uE6M2CKxSuZtqdtiJnoYcmAnDLACDmVHQNbFMEyC3ALrixgTj1p9aYPi8P/9BVKv
+T6cCmRQIl4VY4Ir0PCbai6BQaP6TIbAo0lt9cefUQKBgQDV2KKuc/TsZgrl+ijV
vW1kf46X1Squ8AqPgJnXYM5M4kG+17AecV25sm1oHmzN0ChwvWYotfhLMSqdH+1l
5zMYMwjTle9BkQXELyAvKiKND5I42DtTE04YnHi7HDlaJmOCa3WTTPjJiyIZC+9S
Lpc3gDwP8VSBcq2V2t/SMw9+nQKBgQDCKfIUJWW0WHkESmc8rJDBUWueUVfEWh/d
9ZG/gIapSXnJcTp/fRDZsaqS0pI7c8bvdPJPkQKO0M7Sy2E/OjyKOT5X4+4FguCd
XlwaUhVRycMxGjb1Q4pTlPCnQkoBVKQ5oW4IVQW/ILtT6wuJQPmqkwiXN6CSHzmF
w1RW+pUpNQKBgDXEeHLgmO5vYcIdOfMz47NnFxU59bdyh1U5gnTS1Ewkf19an9+n
pWcxY6zQKY8+DUz7cho+VqWhQROsmWYL0Z7+BfQdOMEFk6uWJcN2FqXdCmjchV4H
9pTdksWI/SqbiF2cYz2cFtml7/bYN140dLTxuyhPB25cxSRumeQiDn1JAoGBAJDf
w2UM0mpSaVmuOoGnMQtNuUMT5qz3ojd3eByvxcqirGCGP+PIab5FNsT+oWYC6Tja
xcJgrMvrOadHYXRP+8QXGlFyHLO4B+jj800gWhAAv8fvi3pNvvTGeRoT+Cwt/6uQ
rA1Dg1otDhl7k8wB00hXFV3ff8wHyF/qcw/DQXDRAoGBAJGvJSl9yIr5v3ooZ6BV
FtDcDTPFGxQCyqvfi5RzKW65Wqu1ZL7jSiOPcY4+418Zifnfyfr/9IZjl9EKPjhC
/fNqptnuA7DKPDKkQIeQSwtHF9HGVoqG0JGOmYCeCZxQK6eZhiuU8VohAAbzsdu8
PgxyS/PRbCsXP4p+OjR1i+3C
-----END PRIVATE KEY-----
)
Try this:
<?php
set_include_path(get_include_path() . PATH_SEPARATOR ."lib");
include('File/X509.php');
$p12cert = array();
$fp=fopen("cert/netclient.p12","r");
$priv_key=fread($fp,8192);
fclose($fp);
openssl_pkcs12_read($priv_key, $p12cert, "abcdefg");
$x509 = new File_X509();
$x509->loadX509($p12cert["cert"]);
$pubkey = $x509->getPublicKey();
$pubkey->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$verified_phpseclib = $pubkey->verify($hash_request, base64_decode(req("signature"))) ? "verified" : "diff";

Categories

Resources