Skip to content

Instantly share code, notes, and snippets.

@hackimov
Created October 4, 2019 05:43
Show Gist options
  • Save hackimov/2d1770ffbfcdbad4853c8826e481e98b to your computer and use it in GitHub Desktop.
Save hackimov/2d1770ffbfcdbad4853c8826e481e98b to your computer and use it in GitHub Desktop.
DSV SERVER EIMZO CLASS LARAVEL DSV SERVER VERIFY SIGN FUNCTION AND DSV SERVER GET DATA SIGNER FROM SIGN
<?php
namespace App\Services;
use GuzzleHttp\Client;
class SignService {
public function is_signature($signature){
# формирование тела SOAP XML запроса отправляемого на сервер
$soap = "
<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\">
<Body>
<verifyPkcs7 xmlns=\"http://v1.pkcs7.plugin.server.dsv.eimzo.yt.uz/\">
<pkcs7B64 xmlns=\"\">$signature</pkcs7B64>
</verifyPkcs7>
</Body>
</Envelope>";
# создаём объект GuzzleHttp (аналог curl)
$http = new Client;
# адрес на который мы будем обращаться
$protocol = 'http://';
$ip = 'YOUR_DSV_SERVER_IP_ADRESS:9090';
$adress = '/dsvs/pkcs7/v1?wsdl';
# сам пост запрос, на удаленный сервер
$response = $http->post($protocol . $ip . $adress, [
'headers' => [
'Content-type' => 'text/xml; charset=utf-8',
],
'body' => $soap,
'http_errors' => false,
'verify' => false,
]);
# получаем данные из тела овета
$result = $response->getBody()->getContents();
# регулярка, на то чтобы вытащить наш ответ из SOAP дарованного папуасами
preg_match("/<return>(.*)<\/return>/Uis", $result, $matches);
# ничего не пришло в ответе, значит либо сервер нам ничего не отослал, либо попути произошла ошибка при передачи информации
if ($matches[0] === '<return></return>') {
return response()->json([
'message' => 'Verification server return no data'
], 400);
} else {
# парсинг входящих данных
$xml = simplexml_load_string($matches[0]);
$answer = json_decode(json_encode((array)$xml), true);
$answer = (array)json_decode($answer[0], true);
$answer = json_decode(json_encode((array)$answer), true);
if(isset($answer['className'],$answer['reason'],$answer['success'])){
if($answer['className'] === 'CMSException' && $answer['reason'] === 'IOException reading content.' && $answer['success'] === false){
return false;
}
if($answer['className'] === 'DecoderException' && $answer['reason'] === 'unable to decode base64 string: invalid characters encountered in base64 data' && $answer['success'] === false){
return false;
}
}
if(isset($answer['pkcs7Info']['signers']['0'], $answer['pkcs7Info']['documentBase64'])) {
$cert = $answer['pkcs7Info']['signers']['0'];
} else {
return false;
}
/**
* Для тех кто не знал:
* true * false === false;
* false * false === false;
* true * true === true;
* грубо говоря , если хотя бы один аргументов умножения false результат примет значение false , что нам сопсна и надо
*/
# проверка валидации сертификата (Хитрожопая система проверки умножением. Данные поля могут иметь значения только true или false );
$verification = (int)$cert['verified'] * $cert['certificateVerified'] * $cert['certificateValidAtSigningTime'];
if($verification === true) {
return true;
} else {
return false;
}
}
}
public function signature_data($signature){
# формирование тела SOAP XML запроса отправляемого на сервер
$soap = "
<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\">
<Body>
<verifyPkcs7 xmlns=\"http://v1.pkcs7.plugin.server.dsv.eimzo.yt.uz/\">
<pkcs7B64 xmlns=\"\">$signature</pkcs7B64>
</verifyPkcs7>
</Body>
</Envelope>";
# создаём объект GuzzleHttp (аналог curl)
$http = new Client;
# адрес на который мы будем обращаться
$protocol = 'http://';
$ip = 'YOUR_DSV_SERVER_IP_ADRESS:9090';
$adress = '/dsvs/pkcs7/v1?wsdl';
# сам пост запрос, на удаленный сервер
$response = $http->post($protocol . $ip . $adress, [
'headers' => [
'Content-type' => 'text/xml; charset=utf-8',
],
'body' => $soap,
'http_errors' => false,
'verify' => false,
]);
# получаем данные из тела овета
$result = $response->getBody()->getContents();
# регулярка, на то чтобы вытащить наш ответ из SOAP дарованного папуасами
preg_match("/<return>(.*)<\/return>/Uis", $result, $matches);
# ничего не пришло в ответе, значит либо сервер нам ничего не отослал, либо попути произошла ошибка при передачи информации
if ($matches[0] === '<return></return>') {
return false;
} else {
# парсинг входящих данных
$xml = simplexml_load_string($matches[0]);
$answer = json_decode(json_encode((array)$xml), true);
$answer = (array)json_decode($answer[0], true);
$answer = json_decode(json_encode((array)$answer), true);
if (isset($answer['className'], $answer['reason'], $answer['success'])) {
if ($answer['className'] === 'CMSException' && $answer['reason'] === 'IOException reading content.' && $answer['success'] === false) {
return false;
}
if ($answer['className'] === 'DecoderException' && $answer['reason'] === 'unable to decode base64 string: invalid characters encountered in base64 data' && $answer['success'] === false) {
return false;
}
}
if (isset($answer['pkcs7Info']['signers']['0'], $answer['pkcs7Info']['documentBase64'])) {
$cert = $answer['pkcs7Info']['signers']['0'];
$crypt_string = $answer['pkcs7Info']['documentBase64'];
$crypt_dec_b64 = base64_decode($crypt_string);
} else {
return false;
}
/**
* Для тех кто не знал:
* true * false === false;
* false * false === false;
* true * true === true;
* грубо говоря , если хотя бы один аргументов умножения false результат примет значение false , что нам сопсна и надо
*/
# проверка валидации сертификата (Хитрожопая система проверки умножением. Данные поля могут иметь значения только true или false );
$verification = (int)$cert['verified'] * $cert['certificateVerified'] * $cert['certificateValidAtSigningTime'];
if ($verification) {
# запихиваем информацию о владельце ключа в переменную
$key_info = $cert['certificate']['0']['subjectName'];
/**
* $first_array = explode (',', $key_info);
* foreach ($first_array as $item) {
* $tmp_arr = explode('=', $item);
* $key_info_arr[$tmp_arr['0']] = $tmp_arr['1'];
* }
*/
# вариант выше тоже работает, но этот укладывается в две строки (если вам не понятно как работает этот код, используете код выше)
$key_chunks = array_chunk(preg_split('/(=|,)/', $key_info), 2);
$key_info_arr = array_combine(array_column($key_chunks, 0), array_column($key_chunks, 1));
# объявляем инкриментатор, и массив который мы будем запихивать данные
$inc = 0;
$key_inner = [];
# преобразуем название колонок в массиве, не как папуасы которые нам их присылают
foreach ($key_info_arr as $item_info) {
# приедем значение к верхнему регистру
$item_info = mb_strtoupper($item_info);
# в зависимости от номера элемента в переборе , присваиваем значение к нужному элементу массива
switch ($inc) {
case 0:
$key_inner['FULL_NAME'] = $item_info;
case 1:
$key_inner['NAME'] = $item_info;
case 2:
$key_inner['SURNAME'] = $item_info;
case 3:
$key_inner['ORGANIZATION'] = $item_info;
case 4:
$key_inner['AREA'] = $item_info;
case 5:
$key_inner['CITY'] = $item_info;
case 6:
$key_inner['COUNTRY'] = $item_info;
case 7:
$key_inner['PIN'] = $item_info;
case 8:
$key_inner['POSITION'] = $item_info;
case 9:
$key_inner['TIN'] = $item_info;
case 10:
$key_inner['TYPE'] = $item_info;
}
$inc++;
}
# очищаем инкрементатор
unset($inc);
# присваивем то что подпись верифицирована, на момент подписания / ключ валидный.
$key_inner['SIGNATURE_VERIFIED'] = $verification;
$key_inner['SIGNED_STRING'] = $crypt_dec_b64;
return $key_inner;
} else {
return false;
}
}
}
}
@ismoil-nosr
Copy link

долго искал ваш гист (забыл сохранить). Вспомнил про папуасов. Загуглил "pkcs7 папуасами" и вот я здесь. Низкий вам поклон!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment