Как проверить подпись PKCS # 7 в PHP - PullRequest
0 голосов
/ 31 мая 2018

У меня должна быть проверена цифровая подпись (зашифрованный формат PKCS # 7), поэтому я попробовал использовать разные основные методы PHP (openssl_verify, openssl_pkcs7_verify и даже попробовал внешнюю библиотеку, такую ​​как phpseclib). Но ничего не помогло: (

По этой ссылке я получаю подпись вместе с некоторыми дополнительными параметрами.

http://URL? Sign = {'param': {'Id': 'XXXXXXX ' 'языки': 'EN', 'Rc': '00', 'Электронная почта': 'test@yahoo.com' '},' подпись ':' DFERVgYJKoZIhvcNAQcCoIIFRzCCBUMCAQExCzAJBgUrDg MCGgUAMIGCBgkqhkiG9w0BBwGgdQRzeyJEYXRlIjoidG9fY2hhcihzeXNkYXRlJ0RETU1ZWVlZJykgIiwiSWQiOiJ VMDExODg3NyIsIklkaW9tYSI6IkNBUyIsIk51bUVtcCI6IlUwM23D4DEE3dSi ...'}

1010 *

PHP-код - возвращает всегда 0 (false) вместо 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-код - (этот код работает и возвращает 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;
}
}

Мне просто нужно преобразовать этот Java-код в PHP. Однако, как вы можете видеть выше, я пробовал разные подходы, но ни один из них не работал.

Пожалуйста, поддержите меня, чтобы найтион решение.

Ваша поддержка будет высоко оценена

...