
We are developing a Flash client for a client-server application with a permanent socket connection and it is important for us to protect ourselves from eavesdropping traffic. One of the methods of such protection is SSL / TLS encryption. In Flash, this can be done in two ways - use the native
SecureSocket or
TLSSocket from the
as3crypto library. Below we discuss the pros and cons, performance, as well as the problems that we encountered in the implementation of both options.
Comparison table
SSL / TLS is a socket add-on to prevent eavesdropping and performs two functions - authentication of participants (server and client) and traffic encryption. The main functionality of sockets for clarity is designed in the form of a table:
Comparison of SecureSocket and TLSSocket, “+” - no problems identified, “-” - not supported or not working, “±” - works but with errors or does not work for all cases, “?” - could not be verified due to previous errors , “-?” - stated that it works, but failed to confirm')
More on the items
Securesocket
Minimal Flash Player Version
SecureSocket requires Flash Player version 11 and above, which is installed only by
75% of users , i.e. for the remaining 25%, in any case, you will have to use
TLSSocket .
Work with certificates
SecureSocket is integrated into the system, which allows it to work with the system certificate store and system authentication tools, i.e. The server certificate will actually be verified through a certificate authority, which
TLSSocket can never do.
SecureSocket also allows you to add your own certificate, which will be considered trusted, but still check it for other errors (expiration date, Common Name mismatch in the certificate and server name) and if anything goes wrong, chop off the connection, therefore the old test certificates (I think almost every developer will have such) most likely will not work.
SSL
SSL 3.0 (hereinafter referred to as SSL always means SSL 3.0) was tested on its servers in the forced SSL mode. The client closed the connection with the unidentified certificate verification status (serverCertificateStatus = invalid) on all certificates that we tried, including the officially signed one. I note that the 443rd port of public servers (google.com, yandex.ru) connects the socket successfully, but the TLS protocol is most likely selected there, and to force the use of only one of the two TLS or SSL protocols
SecureSocket does not allow, just as it does not focus on TLS / SSL settings in the browser in which swf runs. I don’t presume to say that SSL 3.0 does not work in principle, after all, its support is stated in the official documentation, but we couldn’t make it work.
Tls
TLS earned immediately and on both certificates. With a working socket, it was possible to estimate the speed of work compared to the unprotected protocol, here we were in for a big disappointment, more on that below.
Tlssocket
Work with certificates
TLSSocket has several weak points in working with certificates:
- There are various uncorrected bugs when parsing some types of certificates. We didn’t care about the certificate of the certification center and the patch proposed in issue 26 did not help
- You cannot add your own certificate, which will automatically be considered trusted. In tandem with the previous paragraph, we basically lost the opportunity to verify the server certificate. The functionality will have to be added independently (implementation example below), or work in the trustAllCertificates mode, leaving the hole safe .
- There is no possibility to work with certificates installed on the client system. Judging by the presence of the TLSConfig :: localKeyStore property, the idea was, but apparently, the inability of AS3 to program such a list to slow down the implementation has slowed down.
However, there is a positive point, the library provides several flags to work even with non-valid certificates (server name mismatch in certificate and real, self-signed certificates) code openness allows you to add non-functional features (for example, the flag of ignoring certificate expiration or the same adding own certificates)
Patch to add your own trusted certificatesA small patch that adds support for external certificates as trusted in DER format. To implement, simply take the MD5 hash of the entire certificate and compare it with what came from the server, if it is the same - the certificate is trusted.
- In the class com.hurlant.crypto.tls.TLSConfig add methods to add and verify their certificates
public function addTrustedCertificate(cert:ByteArray):void { var md5:String = Hex.fromArray(new MD5().hash(cert)); trustedCertificates[md5] = true; } public function isTrustedCertificate(cert:X509Certificate):Boolean { var md5:String = cert.md5; return trustedCertificates[md5]; }
- In the class com.hurlant.crypto.cert.X509Certificate add a getter on md5 hash and _bytes property (certificate in DER encoding).
private function load():void { ... } else if (p is ByteArray) { b = p; } _bytes = b; ... } private var _bytes:ByteArray; private var _md5:String; public function get md5():String { if(_md5) { return _md5; } if (_bytes) { _md5 = Hex.fromArray(new MD5().hash(_bytes)); } else { throw new Error("get md5: Invalid x509 Certificate parameter"); } return _md5; }
- in the class com.hurlant.crypto.tls.TLSEngine add the verification of the server certificate of trust in the loadCertificates method line 810:
... } else if (_config.isTrustedCertificate(firstCert)) { certTrusted = true; } else if(_config.trustSelfSignedCertificates ) {
Usage example:
package { import com.hurlant.crypto.tls.TLSConfig; import com.hurlant.crypto.tls.TLSEngine; import com.hurlant.crypto.tls.TLSSecurityParameters; import com.hurlant.crypto.tls.TLSSocket; import com.hurlant.util.der.PEM; import flash.display.Sprite; import flash.events.Event; import flash.events.IOErrorEvent; import flash.events.SecurityErrorEvent; import flash.utils.ByteArray; public class addcerttest extends Sprite { [Embed(source="cert.pem", mimeType="application/octet-stream")] private static const cert_pem:Class; public function addcerttest() { var cert_pem_bytes:ByteArray = new cert_pem(); var cert_der:ByteArray = PEM.readCertIntoArray(cert_pem_bytes.readUTFBytes(cert_pem_bytes.bytesAvailable)); var config:TLSConfig = new TLSConfig(TLSEngine.CLIENT, null, null, null, null, null, TLSSecurityParameters.PROTOCOL_VERSION); config.addTrustedCertificate(cert_der); var socket:TLSSocket = new TLSSocket(null, 0, config); socket.addEventListener(Event.CONNECT, log); socket.addEventListener(Event.CLOSE, log); socket.addEventListener(IOErrorEvent.IO_ERROR, log); socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, log); socket.connect("my.app.server", 443); } private function log(event:Event):void { trace(event.type); } } }
SSL / TLS
With
TLSSocket , traffic encryption worked in both protocols, but SSL breaks the encryption of packets on the client after several minutes of client operation. Most likely due to some kind of bugs in the library, they didn’t search because TLS works without problems.
In as3crypto, the
list of bugs is generally quite large and the problem is aggravated by the fact that the developers stopped updating the library.
Performance
Securesocket
A new problem has arisen with SecureSocket - periodically (every 5-10 requests) the socket “goes to itself” for 2-8 seconds for no apparent reason. I do not presume to say that everyone will have such lags, but we had them, moreover, on the same server. on which the
TLSSocket worked quickly, i.e. Deal on the client side. Tested in a “clean” demo without binding in the form of an application. The dependence of the parsing time on the packet size could not be established, we tried packets from 30 bytes to 5 kb, hangs appeared at different times on random packets, the processor did not load during hangs, fps did not fall. The very same packet parsing is fast, if you only take packets without hanging the difference between
Socket and
SecureSocket imperceptibly, while
TLSSocket is still slower than
Socket . I'll try to deal with this later, because I would like to still have a fast-running native version.
Tlssocket
Since the whole implementation here for as3 packet parsing time is linearly proportional to the size and for 2-7 kb packets (maximum in our project) on core i7 was 40-120 ms, respectively, small packets with runtime alerts parry up (5-20 ms for packets 100-500 bytes) and do not cause any lags. For a user, adding SSL / TLS will be noticeable only on large packets.
Swf display
All checked and debugged, now, we lay out the assembly on the http server, not forgetting to configure the
socket policy server . We start the application, we see that both sockets do not work. Each has its own reasons:
TLSSocket does not work due to
issue 4 - the client sends a request for a “handshake” before the connection is established. With
SecureSocket it is a bit more difficult for Flash Player to allow TLS / SSL connection to open, the policy file from the server will have to be sent via TLS / SSL protocol, i.e. need to refine the distributor of this file.
findings
SecureSocket is integrated into the system, which allows it to work with the system certificate store and system authentication tools, which
TLSSocket cannot boast of. However, the advantages of
SecureSocket end there. Of the obvious flaws, I note second-lags when parsing incoming data, broken SSL 3.0 and debugging silence in general if something does not work, typical of many native as3 solutions.
TLSSocket , on the other
hand , is distinguished by its fast speed and the ability to correct (or at least understand the reason) errors in the work, providing its source code.
Thanks, who read to the end, I hope the material will be useful and someone will save time. Typos and errors please send in PM. Inaccuracies and additions will be glad to discuss in the comments.
Link to GitHub
as3crypto_patched with patches that were mentioned in the article and the functionality to add external trusted certificates.