openssl, шифрование и подпись

bars80081

Новичок
Добрый день,

у меня возникла проблема, видимо, связанная исключительно с моей внимательностью.
проблема: отправляю зашифрованное и подписанное сообщение на удалённый сервер, он отвечает "ключ неверен".
пишу сюда только потому, что не знаю что делать. вдруг допустил какую-то невероятно глупую ошибку при пользовании библиотекой openssl, а вы её сразу увидите

задача:
текст шифруется открытым ключом шлюза и, подписав SHA1-дайджест зашифрованного сообщения при помощи своего закрытого ключа, отправляется на шлюз

сервер работоспособен и отлажен, ибо другие с ними работают без проблем
сокетное соединение также налажено и проверено при помощи нешифрованных запросов
ключи сгенерированы непосредственно на той же машине, с которой происходит отсылка запросов.
генерация ключей происходила этим кодом (который я благополучно скопипастил без размышления над его сущностью):

PHP:
	static function generateKeys($bits_count = 1024) {
		//generate public key
		$params = array(
			'digest_alg' => 'sha1',
			'private_key_bits' => $bits_count,
			'private_key_type' => OPENSSL_KEYTYPE_RSA,
			'encrypt_key' => false
		);
		$private_key = openssl_pkey_new($params);
		openssl_pkey_export($private_key, $private_key_string);
		
		//generate certificate (to get a public key from it)
		$csr = openssl_csr_new(array(), $private_keys);
		$cert = openssl_csr_sign($csr, null, $private_key, 1);
		openssl_x509_export($cert, $str_cert);
		
		//get the public key from the certificate
		$public_key = openssl_pkey_get_public($str_cert);
		//get the PEM-encoded public key
		$public_key_details = openssl_pkey_get_details($public_key);
		$public_key_string = $public_key_details['key'];
		
		return array('private' => $private_key_string, 'public' => $public_key_string);
	}
у меня небольшие опасения по поводу функции openssl_x509_export(). не может ли она быть специфичной функцией для определённого типа шифрования. у меня в условиях были только RSA, паддинг PKCS1 и SHA1.

шифрование и отсылка сообщений происходит следующим кодом:


PHP:
$key = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANfSTfT8TX9ik
... ещё 2 строчки ...
KDVXfcZAo2fmazFv+QIDAQAB
-----END PUBLIC KEY-----';
$sirena->public_key = $key;
$key = '-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANfSTfT8+bfSTtF3
... ещё 12 строчек ...
luTHbgAuBgeJGpA=
-----END PRIVATE KEY-----';
$sirena->private_key = $key;
$key = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANfSTfT8VOiDOP
... ещё 2 строчки ...
Ya9y4c56YQhoWGo6hwIDAQAB
-----END PUBLIC KEY-----';
$sirena->server_public_key = $key;

$message = '12341234';

$sirena->set_crypted_open_message($message);
$q = $sirena->send();


class sirena {
	public $public_key = '';
	public $private_key = '';
	public $server_public_key = '';
	
	private $message = '';
	private $header = '';
	
	private function public_encrypt($data, $public_key = '') {
		$result = openssl_public_encrypt($data, $crypted, $public_key, OPENSSL_PKCS1_PADDING);
		return $crypted;
	}
	private function sign($data, $private_key = '') {
		$key_id = openssl_pkey_get_private($private_key);
		$result = openssl_sign($data, $signature, $key_id, OPENSSL_ALGO_SHA1);
		openssl_free_key($key_id);
		return $signature;
	}
	public function set_crypted_open_message($s = '') {
		$message_encrypt = $this->public_encrypt($s, $this->server_public_key);
		$message_len = strlen($message_encrypt);
		
		$subscribe = $this->sign($s, $this->private_key);

		// формат сообщения: 4 байта на длину тела + тело сообщения + подпись
		$res = pack('N', $message_len);
		$res .= $message_encrypt;
		$res .= $subscribe;
		
		$this->message = $res;
	}
	public function send() {
		$this->set_header(); // возвращает 100-байтовый заголовок, отлаженный, как и сокетное соединение. сервер его понимает
		
		$query = $this->header . $this->message;
		$q = $this->socketer->write($query);
		
		return $q;
	}
}
сервер полностью воспринимает, что ему приходит. он читает заголовок, узнаёт из него (выставлен флаг), что сообщение зашифровано. возвращает ошибку: "неверный ключ", то есть не получается расшифровать.

в общем, надеюсь в этой теме только на то, что ваш натренированный глаз вдруг вычленит несуразную ересь в моём коде.
 

bars80081

Новичок
послушайте, а может в RSA-шифровании есть какой-то иной стандарт, помимо X.509?

или может мне следовало где-нибудь что-нибудь зарегистрировать, чтобы начать пользоваться шифрованием?

да, и мучает ещё один вопрос: а сертификат на сервере сохраняется постоянно? я так понял, что весь процесс происходит при наличие некоторого ключевого файла, типа базового сертификата. он ведь один на всех? он же не пересоздаётся постоянно?
 
Сверху