How to verify PKCS#7 signature in PHP - ssl

I have a digital signature (encrypted format PKCS#7) needs to be verified So I have tried by using different PHP core methods(openssl_verify, openssl_pkcs7_verify and even tried by external library such as phpseclib But nothing worked :(
I get a signature along with some extra params through by this link..
http://URL?sign={'param':{'Id':'XXXXXXX','lang':'EN','Rc':'00','Email': 'test#yahoo.com'’},'signature':'DFERVgYJKoZIhvcNAQcCoIIFRzCCBUMCAQExCzAJBgUrDg
MCGgUAMIGCBgkqhkiG9w0BBwGgdQRzeyJEYXRlIjoidG9fY2hhcihzeXNkYXRlJ0RETU1ZWVlZJykgIiwiSWQiOiJ
VMDExODg3NyIsIklkaW9tYSI6IkNBUyIsIk51bUVtcCI6IlUwM23D4DEE3dSi...'}
PHP code - returns always 0(false) instead of 1(true).
$JSONDATA = str_replace("'", '"', #$_GET["sign"]);
$data = json_decode($JSONDATA, true);
$this->email = $data['param']["EMAIL"];
$this->signature = $data['signature'];
$this->signature_base64 = base64_decode($this->signature);
$this->dataencoded = json_encode($data['param']);
//SOLUTION 1 (By using phpseclib) but didnt work..
$rsa = $this->phpseclib->load();
$keysize = 2048;
$rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS8);
$rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1);
$d = $rsa->createKey($keysize);
$Kver = $d['publickey'];
$KSign = $d['privatekey'];
// Signing
$rsa->loadKey($KSign);
$rsa->setSignatureMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$rsa->setHash('sha256');
$signature = $rsa->sign($this->dataencoded);
$signedHS = base64_encode($signature);
// Verification
$rsa->loadKey($Kver);
$status = $rsa->verify($this->dataencoded, $this->firma_base64); // getting an error on this line Message: Invalid signature
var_dump($status); // reutrn false
//SOLUTION 2 (By using code php methods)
// obtener la clave pública desde el certifiado y prepararla
$orignal_parse = parse_url("https://example.com", PHP_URL_HOST);
$get = stream_context_create(array("ssl" => array("capture_peer_cert" => TRUE)));
$read = stream_socket_client("ssl://".$orignal_parse.":443", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $get);
$cert = stream_context_get_params($read);
$certinfo = openssl_x509_parse($cert['options']['ssl']['peer_certificate']);
openssl_x509_export($cert["options"]["ssl"]["peer_certificate"],$cert_key);
$pubkeyid = openssl_pkey_get_public($cert_key);
$dataencoded = json_encode($data['param']);
echo $ok = openssl_x509_check_private_key($cert_key,$this->firma_base64); // return nothing
echo $ok1 = openssl_verify($dataencoded, $this->firma_base64, $pubkeyid, OPENSSL_ALGO_SHA256); // returns 0
echo $ok2 = openssl_verify($dataencoded, $this->firma_base64, $pubkeyid, OPENSSL_ALGO_SHA512); // returns 0
echo $ok3 = openssl_verify($dataencoded, $this->firma_base64, $pubkeyid, OPENSSL_ALGO_SHA256); // returns 0
echo $ok4 = openssl_verify($dataencoded, $this->firma, $pubkeyid, OPENSSL_ALGO_SHA512); // returns 0
Java code - (this code works and returns true)
private boolean verifySignautre(String frm) throws NetinfException, IOException, CMSException,
CertificateException, OperatorCreationException, Exception {
Security.addProvider(new BouncyCastleProvider());
//we extract the containers that make up the signature and the keystore used to sign included in the same signature.
CMSSignedData signedData = new CMSSignedData(Base64.decode(frm.getBytes()));
SignerInformationStore signers = signedData.getSignerInfos();
Store certStore = signedData.getCertificates();
Collection c = signers.getSigners();
Iterator it = c.iterator();
while (it.hasNext()) {
//retrieve the certificate with the recipient's id.
SignerInformation signerInfo = (SignerInformation) it.next();
Collection certCollection = certStore.getMatches(signerInfo.getSID());
Iterator certIt = certCollection.iterator();
X509CertificateHolder signerCertificateHolder = (X509CertificateHolder) certIt.next();
//create the container to validate signature.
ContentVerifierProvider contentVerifierProvider = new BcRSAContentVerifierProviderBuilder(new
DefaultDigestAlgorithmIdentifierFinder()).build(signerCertificateHolder);
//valid signature and then certificate validity date
try{
X509Certificate signedcert = new
JcaX509CertificateConverter().setProvider("BC").getCertificate(signerCertificateHolder);
signedcert.checkValidity();
signedcert.verify(signedcert.getPublicKey());
return true;
}catch(Exception e){
return false;
}
}
I simply need to convert this Java code into PHP. However, as you can see above that I tried different approaches but none of them worked.
Please support me to find the solution.
your support would be higly appreciated

Related

Kreait : verifySessionCookie() not found

I try to verify a session cookie from the $sessionCookieString = $auth->createSessionCookie($idToken, $oneWeek); which work normally.
But report say that the function is not found.
"Call to undefined method Kreait\Firebase\Auth::verifySessionCookie()"
Didn't understand why.
i have the latest version install.
--- Portion of code below ---
use Kreait\Firebase\Factory;
use Kreait\Firebase\Contract\Auth;
use Kreait\Firebase\Auth\UserQuery;
use Google\Cloud\Firestore\FirestoreClient;
use Kreait\Firebase\Auth\CreateSessionCookie\FailedToCreateSessionCookie;
public function doLogin() {
$factory = (new Factory)->withServiceAccount($this->ekonysJson );
$auth = $factory->createAuth();
$this->auth = $auth;
//print_r($auth);
$signInResult = $auth->signInWithEmailAndPassword("email#dot", "password");
$idToken = $signInResult->idToken();
`print_r($signInResult->refreshToken());`
$oneWeek = new \DateInterval('P7D');
$sessionCookieString = $auth->createSessionCookie($idToken, $oneWeek);
$verifiedSessionCookie = $auth->verifySessionCookie($sessionCookieString)
}
refer to doc https://firebase-php.readthedocs.io/en/stable/authentication.html#session-cookies
if you have any idea.... thanks
Solution for this problem

Zoho Creator API Integration Basic Authorization postUrl()

Here is my code and I am getting Internal Error for postural() call. By the way, one more thing I want to know how we can use verify_peer to 0(zero) for not using SSL things. What is wrong with my code?
void SendSMS(SMS SMSObject)
{
//CONFIGURATION
URL = "https://example.com/send_ack.php";
wbLogin = "wbLogin";
wbPwd = "wbPwd";
wbAccount = "wbAccount";
label = "label";
applicationName = "ADR SMS v1.0";
//BASE64 ENCODING
Base64Encoded = zoho.encryption.base64Encode("httpLogin:httpPwd");
AuthorizationBasic = "Authorization: Basic " + Base64Encoded;
//HEADER
HeaderMap = Map();
HeaderMap.put("content-type", "application/x-www-form-urlencoded");
HeaderMap.put("Authorization", AuthorizationBasic);
//REQUEST
RequestMap = Map();
RequestMap.put("compte", wbAccount);
RequestMap.put("op", 1);
RequestMap.put("type", 0);
RequestMap.put("dt", zoho.currentdate.getDay());
RequestMap.put("hr", zoho.currenttime.getHour());
RequestMap.put("mn", zoho.currenttime.getMinutes());
RequestMap.put("label", label);
RequestMap.put("dest_num", "phone_number");
RequestMap.put("msg", "ZC Testing");
RequestMap.put("ref", "ZC");
//CALL POSTURL
Result = postUrl(URL, RequestMap, HeaderMap, false);
//DEBUG
info Result;
}
Use Zoho Creator API for this purpose.

lua https.request with certificate

I'm trying to make a request on lua with certificate.
Recently I've gotten a COMODO SSL.
I've tried many tutorials on the internet, but to no avail.
I found this blog's proposal very interesting:
I am not getting able to execute the request on Linux/OpenWRT/Lua 5.1.
COMODO has provided me with the following files:
AddTrustExternalCARoot.crt
my_domain_com.crt
COMODORSAAddTrustCA.crt
COMODORSADomainValidationSecureServerCA.crt
And in this blog he mentions these files:
key = "/root/client.key"
certificate="/root/client.crt",
cafile="/root/ca.crt"
How do I convert the COMODO's .crt files the to those mentioned in the blog?
Obs: I tried to download with curl and get, but it did not work.
I've described the details in a blog post; basically, you need to specify the mode and the certificate file for the ssl.wrap call:
local params = {
mode = "client",
protocol = "tlsv1",
cafile = "/path/to/downloaded/cacert.pem", --<-- added cafile parameters
verify = "peer", --<-- changed "none" to "peer"
options = "all",
}
If you need to convert .crt to .pem file, then the following SO answer may help. I haven't tried with .crt, but the examples I have work with .pem files.
I solve it with this code:
module("https", package.seeall)
local socket = require "socket"
local http = require "socket.http"
local ssl = require "ssl"
local ltn12 = require "ltn12"
local try = socket.try
local protect = socket.protect
local DEFAULT_PROTOCOL = "sslv23"
local DEFAULT_CAFILE = "/etc/ssl/certs/ca-certificates.crt"
local DEFAULT_VERIFY = "peer"
local DEFAULT_OPTIONS = "all"
local DEFAULT_CIPHERS = "ADH-AES256-SHA:ADH-AES128-SHA:HIGH:MEDIUM"
local DEFAULT_HTTPS_PORT = 443
local https_mt = {
-- Create proxy functions for each call through the metatable
__index = function(tbl, key)
local f = function(prxy, ...)
local c = prxy.c
return c[key](c, ...)
end
tbl[key] = f -- Save new proxy function in cache for speed
return f
end
}
local function new_create(params)
return function()
local t = { c = try(socket.tcp()) }
function t:connect(host, port)
try(self.c:connect(host, port))
self.c = try(ssl.wrap(self.c, params))
try(self.c:dohandshake())
return 1
end
return setmetatable(t, https_mt)
end
end
local function request_generic(args)
local sslparams = {
mode = "client",
protocol = args.protocol or DEFAULT_PROTOCOL,
cafile = args.cafile or DEFAULT_CAFILE,
verify = args.verify or DEFAULT_VERIFY,
options = args.options or DEFAULT_OPTIONS,
ciphers = args.ciphers or DEFAULT_CIPHERS
}
local req = {
url = args.url,
port = args.port or DEFAULT_HTTPS_PORT,
sink = args.sink,
method = args.method,
headers = args.headers,
source = args.source,
step = args.step,
proxy = args.proxy, -- Buggy?
redirect = args.redirect,
create = new_create(sslparams)
}
return http.request(req)
end
local function request_simple(url, body)
local tbl = { }
local req = {
url = url,
sink = ltn12.sink.table(tbl)
}
if body then
req.method = "POST"
req.source = ltn12.source.string(body)
req.headers = {
["Content-length"] = #body,
["Content-type"] = "application/x-www-form-urlencoded"
}
end
local _, status, headers = request_generic(req)
return table.concat(tbl), status, headers
end
function request(req_or_url, body)
if type(req_or_url) == "string" then
return request_simple(req_or_url, body)
else
return request_generic(req_or_url)
end
end

InsertAll using C# not working

I´d like to know why this code is not working. It runs without errors but rows are not inserted. I´m using C# client library.
Any ideas? Thanks!!
string SERVICE_ACCOUNT_EMAIL = "(myserviceaccountemail)";
string SERVICE_ACCOUNT_PKCS12_FILE_PATH = #"C:\(myprivatekeyfile)";
System.Security.Cryptography.X509Certificates.X509Certificate2 certificate =
new System.Security.Cryptography.X509Certificates.X509Certificate2(SERVICE_ACCOUNT_PKCS12_FILE_PATH, "notasecret",
System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(SERVICE_ACCOUNT_EMAIL)
{
Scopes = new[] { BigqueryService.Scope.BigqueryInsertdata, BigqueryService.Scope.Bigquery }
}.FromCertificate(certificate));
// Create the service.
var service = new BigqueryService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "test"
});
Google.Apis.Bigquery.v2.Data.TableDataInsertAllRequest tabreq = new Google.Apis.Bigquery.v2.Data.TableDataInsertAllRequest();
List<Google.Apis.Bigquery.v2.Data.TableDataInsertAllRequest.RowsData> tabrows = new List<Google.Apis.Bigquery.v2.Data.TableDataInsertAllRequest.RowsData>();
Google.Apis.Bigquery.v2.Data.TableDataInsertAllRequest.RowsData rd = new Google.Apis.Bigquery.v2.Data.TableDataInsertAllRequest.RowsData();
IDictionary<string,object> r = new Dictionary<string,object>();
r.Add("campo1", "test4");
r.Add("campo2", "test5");
rd.Json = r;
tabrows.Add(rd);
tabreq.Rows = tabrows;
service.Tabledata.InsertAll(tabreq, "(myprojectid)", "spots", "spots");
I think you should add the Kind field [1]. It should be something like this:
tabreq.Kind = "bigquery#tableDataInsertAllRequest";
Also remeber that every request of the API has a response [2] with additional info to help you find the issue's root cause.
var requestResponse = service.Tabledata.InsertAll(tabreq, "(myprojectid)", "spots", "spots");
[1] https://developers.google.com/resources/api-libraries/documentation/bigquery/v2/csharp/latest/classGoogle_1_1Apis_1_1Bigquery_1_1v2_1_1Data_1_1TableDataInsertAllRequest.html#aa2e9b0da5e15b158ae0d107378376b26
[2] https://cloud.google.com/bigquery/docs/reference/v2/tabledata/insertAll

Web Deploy API and Web Management Service (WMSVC)

I'm trying to translate the following WORKING command line into web deploy api (Microsoft.Web.Deployment) code:
"C:\Program Files (x86)\IIS\Microsoft Web Deploy V3\msdeploy.exe" -verb:sync -source:contentPath="\\myserver\code_to_deploy" -dest:contentPath="Default Web Site",wmsvc="mysandbox",userName="MyWebDeployUser",password="MyPassword" -allowUntrusted
My looks like this:
string srcPath = "\\myserver\code_to_deploy";
string destPath = "Default Web Site";
DeploymentBaseOptions sourceOptions = new DeploymentBaseOptions();
sourceOptions.TraceLevel = TraceLevel.Verbose;
sourceOptions.Trace += new EventHandler<DeploymentTraceEventArgs>(Src_Trace);
DeploymentBaseOptions destOptions = new DeploymentBaseOptions();
destOptions.UserName = "MyWebDeployUser";
destOptions.Password = "MyPassword";
destOptions.AddDefaultProviderSetting("contentPath", "wmsvc", "mysandbox");
destOptions.AuthenticationType = "basic";
destOptions.TraceLevel = TraceLevel.Verbose;
destOptions.Trace += new EventHandler<DeploymentTraceEventArgs>(Dest_Trace);
ServicePointManager.ServerCertificateValidationCallback = (s, c, chain, err) =>
{
return true;
};
DeploymentSyncOptions syncOptions = new DeploymentSyncOptions();
syncOptions.DeleteDestination = true;
using (DeploymentObject depObj = DeploymentManager.CreateObject(DeploymentWellKnownProvider.ContentPath, srcPath, sourceOptions))
{
var summary = depObj.SyncTo(DeploymentWellKnownProvider.IisApp, destPath, destOptions, syncOptions);
}
When the code makes the call to 'AddDefaultProviderSetting' it fails saying that wmsvc is not supported by the provider. If I remove the line I receive a 401 from the server. Any examples of doing this or other help is much appreciated.
I don't know whether you have found a solution but here is a code snippet that allows to use wmsvc for those who need it:
DeploymentBaseOptions destinationOptions = new DeploymentBaseOptions()
{
UserName = "<user_name>",
Password = "<password>",
IncludeAcls = false,
AuthenticationType = "Basic",
UseDelegation = true,
ComputerName = "https://<server>:8172/msdeploy.axd?Site=<website>"
};
// Use -allowUntrusted option
ServicePointManager.ServerCertificateValidationCallback +=
new RemoteCertificateValidationCallback(
(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => { return true; });
string package = <zip_package_fullPath>;
string parameters = <project_SetParameters_xml_fullPath>;
using (var deploymentObject = DeploymentManager.CreateObject(DeploymentWellKnownProvider.Package, package))
{
deploymentObject.SyncParameters.Load(parameters);
DeploymentSyncOptions syncOptions = new DeploymentSyncOptions();
DeploymentChangeSummary results = deploymentObject.SyncTo(destinationOptions, syncOptions);
}
It's quite hard to find documentation on these topics. Btw, I've not succeeded in using AddDefaultProviderSetting, even by creating a .exe.configSettings file and I'm not sure it's the right method to achieve what you want to.
To create a virtual application instead of a website, only .SetParameters.xml has to be changed from
<setParameter name="IIS Web Application Name" value="<WebSite>" />
to
<setParameter name="IIS Web Application Name" value="<WebSite>/<VirtualApp>" />
Hope this helps.