3

I am trying to set up a secure websocket connection, however my data does not seem to get decrypted. Tried several methods of reading the data, but non works.

Does anyone has a clue what causes this?

My socket server

//Create the main socket
$context = stream_context_create();

// local_cert must be in PEM format
stream_context_set_option($context, 'ssl', 'local_cert', '/storage/chat/Jongeren.pem');
stream_context_set_option($context, 'ssl', 'passphrase', '*****');

// Create the server socket
$this->master = stream_socket_server(
        "tls://$addr:$port",
        $errno,
        $errstr,
        STREAM_SERVER_BIND|STREAM_SERVER_LISTEN,
        $context
);
stream_set_blocking($this->master, 0);
$this->Sockets['master'] = $this->master;

if($errno > 0){ //An error has occured
    log::debug("Main socket error ($errno): $errstr");
    die();
} else {
    log::info("Main socket started, listening on $addr:$port");
}

while(true) {
  //Select sockets witch activity
  $read = $this->Sockets;
  $changed = stream_select($read,$write,$except,1);

    //Process changed
    if( (false !== $changed) && ($changed > 0) ){

        //Accept new connections
        if( in_array($this->master, $read) ){
            $new_client = stream_socket_accept($this->master, 1, $remote_host);
            if ($new_client) {              
                $index = uniqid();
        $this->Sockets[$index] = $new_client;
        $this->users[$index] = new $this->userClass($remote_host);
        $this->ConnectionSettings[$index] = new Connection();
        log::info('incoming connection: '.$remote_host);
        log::info('client count: '. (count($this->Sockets)-1) );
      } else {
                $err = socket_last_error($socket);
        log::debug("Socket error: ".$err.": ".socket_strerror($err), NULL,NULL);
            }
        }

        //delete the server socket from the read sockets
    unset($read['master'], $new_client, $remote_host);

    //Process changed sockets
    foreach ($read as $socket) {

             if( false !== ($buffer = stream_socket_recvfrom($socket,8192) ) ){
                $sID = $this->getSocketID($socket);
                if( empty( $buffer ) ){
                    $this->disconnect($sID, false);
                } else {
                    log::info( 'Data: '.$buffer );
                }
            }
    }
  }
}

The data output:

2015-12-03T21:35:46+01:00 >> Main socket started, listening on 192.168.1.100:9090
2015-12-03T21:35:51+01:00 >> incoming connection: 192.168.1.1:43022
2015-12-03T21:35:51+01:00 >> client count: 1
2015-12-03T21:35:51+01:00 >> Data: lw���ٮ(0�����MO��gyp��³sy��,b7��>��-�F�}ǮsF'g�EMg�c8�
                                                                                                     �F
 �z�F�k{    5�dP�IQ�+��ڞ���~�Q������h5v��Z��FEɸ�� .�~�͉���ªgf\=���Y>�2�
H�_��E�qS��� ����I��.�W
                        /�V �
�Z\���
�u���o�����"�V�)J[���;>�O��y���3?��,��'Ğ-�y�3ݱ1qid�;He�2o�(wyo��C����rt��{[K%�U2�'����"�_�ζA���m
                                                                                                     7�4* ���4ؑ����_���Y�7RO�˝�}J�t���Д�Iݼ`�&KƉ�pƫ,�x�
                                                   �l'~/���NL,��@��<ݿ�U{��'�7r5��w��X�|Va�~f���^���R��5��������Y�K0��.QN�c'�p{-c��߼y�{��Ыr���:ZʬH͞$\�Tl��SQ��*��[���7|#
                                                                               S0�����F���Sh)bL3&�E
      ���czE��J�#��Q.��Q    �����'�E
7
  • Not familiar with this, but you're specifying ssl as the wrapper in stream_context_set_option(), but then calling a tls:// URL. Have you tried setting both to tls? Second thought: do you need to run stream_socket_enable_crypto()? I'd imagine the tls:// URL would do it automatically, but not sure. Commented Dec 3, 2015 at 20:49
  • @miken32: triedstream_socket_enable_crypto(), but got the responce it was already enabled for the sockets. Both ssl:// as tls:// give same result Commented Dec 3, 2015 at 22:55
  • php.net/manual/en/function.stream-socket-recvfrom.php says fread should give decrypted data. I tried that, but didn't work. Will give it another try tomorrow. Commented Dec 3, 2015 at 23:02
  • Update: fread gives the same result Commented Dec 4, 2015 at 20:16
  • Just came across this (I'm currently doing some socket programming myself, but not encrypted) does the sample code help? It's opening the stream with a tcp:// wrapper and then enabling crypto afterwards. stackoverflow.com/a/22003476/1255289 Commented Dec 4, 2015 at 21:49

1 Answer 1

1

I finally solved it.

//Create the main socket
$context = stream_context_create();

// local_cert must be in PEM format
stream_context_set_option($context, 'ssl', 'local_cert', 'file.pem');
stream_context_set_option($context, 'ssl', 'passphrase', '***');
stream_context_set_option($context, 'ssl', 'allow_self_signed', true);
stream_context_set_option($context, 'ssl', 'verify_peer', false);

// Create the server socket
$this->master = stream_socket_server(
            "ssl://$addr:$port",
            $errno,
            $errstr,
            STREAM_SERVER_BIND|STREAM_SERVER_LISTEN,
            $context
    );

$this->Sockets['master'] = $this->master;

if($errno > 0){ //An error has occured
  log::debug("Main socket error ($errno): $errstr");
  die();
} else {
  log::info("Main socket started, listening on $addr:$port");
}

while(true) {

  //Select sockets witch activity
  $read = $this->Sockets;
  stream_select($read,$write,$except,60);

  if(count($read) > 0){
$t = count($this->Sockets)-1;
$r = count($read);
$w = count($write);
$e = count($except);
log::info( 'T:'.$t.' R:'.$r.' W:'.$w.' E:'.$e );
  }

  //Accept new connections
  if( in_array($this->master, $read) ){
$new_client = stream_socket_accept($this->master, 1, $remote_host);
    if ($new_client) {
    $index = uniqid();
    $this->Sockets[$index] = $new_client;
        $this->users[$index] = new $this->userClass($remote_host);
        $this->ConnectionSettings[$index] = new Connection();
        log::info('Accepted connection: '.$remote_host);
    } else {
        $err = socket_last_error($socket);
        log::debug("Socket error: ".$err.": ".socket_strerror($err), NULL,NULL);
    }
  }

  //delete the server socket from the read sockets
  unset($read['master'], $new_client, $remote_host );

  //Process changed sockets
  foreach ($read as $socket) {
$buffer = fread($socket, 2046);

    $sID = $this->getSocketID($socket);
if( empty( $buffer ) ){
  $this->disconnect($sID, false);
} else {
  log::info( 'Data: '.$buffer );
  if (!$this->ConnectionSettings[$sID]->shake) {  //HANDSHAKE
    $this->doHandshake($sID,$buffer);
      } else if ($message = $this->deframe($sID, $buffer)) { //MESSAGE
    $this->process($sID, utf8_encode($message));
  }
}
  }
  //cleanup
  unset($read,$r,$write,$w,$except,$e,$socket,$buffer);
}

The problem was that I did not use the right certificate. How stupid of me :(

So these things are important:

  • Use the right conntion string that is consistent with the certificate regarding the IP adres or domain
  • Have the privatekey, certificate, intermediate, CA in the pem file in this order.
  • use fread and frwrite to communicate
Sign up to request clarification or add additional context in comments.

1 Comment

Is there no way to use stream_socket_recvfrom instead of fread and get decrypted data?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.