/** * * @param string $user * @param string $byte_array_challenge * @param string $wsdl * @param string $endpoint * @param string $responsys_public_cert_path * @param string $client_private_key_path */ public function loginWithCertificate($user, $byte_array_challenge, $wsdl, $endpoint, $responsys_public_cert_path, $client_private_key_path) { if (self::$isLoggedIn) { if ($this->debug) { echo "Attempt to loginWithCertificate when already logged in"; } return false; } // RESPONSYS PUBLIC CERT $responsys_certificate_file = file_get_contents($responsys_public_cert_path); // PRIVATE KEY REQUIRED FOR ENCRYPTING SERVER CHALLENGE - obtained from openssl cert & key creation process $mdixon_certificate_file = file_get_contents($client_private_key_path); $byte_array = array(); $container = array(); $container2 = array(); $container3 = array(); // Convert to integer for java $len = strlen($byte_array_challenge); for ($i = 0; $i < $len; $i++) { $byte_array[] = ord($byte_array_challenge[$i]); } // Run authServer call to verify user and get a temporary sessionId for login call $result = $this->authServer($user, $byte_array, $wsdl, $endpoint); //print_r( $result ); $authId = $result->result->authSessionId; $encServerChallenge = $result->result->encryptedClientChallenge; $serverChallenge = $result->result->serverChallenge; // Hack to deal with null returns in challenge strings ( weak! ) // The trick is setting the null value to 128 - which should actually be out of range for java since it uses -128 through 127 but it works... foreach ($encServerChallenge as $key => $val) { $val = trim($val); if (isset($val) && $val !== null && $val !== "") { $container[] = $val; } else { $container[] = 128; } } // Now we have to decrypt the binary string $decryptMe = $this->packer($container); // USE RESP CERT TO DECYRPT THE VALUE AND DIFF ON ORIGINAL STRING VALUE !!! // GET A X509 INSTANCE, THEN GET THE PUBLIC KEY FOR openssl_public_decrypt $x509 = openssl_x509_read($responsys_certificate_file); openssl_x509_export($x509, $newX509); $pubKey = openssl_get_publickey($newX509); if (openssl_public_decrypt($decryptMe, $decrypted, $pubKey, OPENSSL_PKCS1_PADDING)) { $data = $decrypted; } else { throw new Exception("Failed to decrypt the challenge " . openssl_error_string()); } // Compare the original string to the decrypted data string // If this matches then the decryption logic is proper, and we proceed to login call if ($byte_array_challenge == $data) { // Get the private key for encrypting the return $private_key = openssl_get_privatekey($mdixon_certificate_file); foreach ($serverChallenge as $j => $b) { $val2 = trim($b); if (isset($val2) && $val2 !== null && $val2 !== "") { $container2[] = $val2; } else { $container2[] = 128; } } $encryptMe = $this->packer($container2); if (!openssl_private_encrypt($encryptMe, $encryptedData, $private_key, OPENSSL_PKCS1_PADDING)) { throw new Exception("Failed to Encrypt data with Private Key - exiting"); } // Now we have to unpack data which converts unsigned encrypted data to signed byte type // to play nice with java signed byte type $unpackedData = unpack('c*', $encryptedData); // Now iterate through bytes, and set the 128 values to null since API allows / sends nulls foreach ($unpackedData as $m => $d) { $val3 = trim($d); if ($val3 == 128) { $container3[] = null; } else { $container3[] = $val3; } } // Now we have all of the parts, set the authId as the session id for the login call, and send in the prepared encrypted server challenge // If all goes well we will get a sessionId in the result of the upcoming call. $this->setSoapHeaders($authId); $this->setSessionCookie(); $loginWithCertObj = new loginWithCertificate($container3); $result = $this->execute($loginWithCertObj); if ($result) { $this->sessionId = $result->result->sessionId; if (!$this->setSoapHeaders() || !$this->setSessionCookie()) { throw new Exception(self::SOAP_ERROR_HEADER); } self::$isLoggedIn = true; } else { throw new Exception(self::SOAP_ERROR_LOGIN); } //print_r( $result ); return $result; } else { throw new SoapFault("Problem during handshake - exiting"); } }