47441

Codesigning SWF?

Question:

AIR allows to inject code using Loader.LoadBytes()

this allows to download remote plugins as swf files which will have full access to everything that the AIR application has access to. This imposes a security risk, so it would be desirable to digitally sign the swf's.

What's the best way to do this and to verify the code signature?

I know the as3corelib has some encryption functionality and also for X.509 certificate - but I didn't find a ressource explaining how to use it. Also, maybe there's some 'official' way to codesign SWF's?

Answer1:

One robust method is using public key encryption, which goes something like this:

<ol><li>You will need an asymmetric encryption algorithm (eg, RSA), and a hash algorithm (eg, SHA, MD5). </li> <li>Generate a public-private key pair.</li> <li>Generate and checksum of the data using the hash algorithm.</li> <li>Encrypt the checksum with the private key using the encryption algorithm. This becomes the "signature".</li> <li>Send the data to the client along with the signature.</li> <li>Decrypt the signature on the client with the public key to obtain the original checksum. </li> <li>Generate a checksum from the data on the client.</li> <li>Compare the checksums. If they match, then you know that the data came from you without alterations. If they do not match then you know the data was altered after it was sent from you, or it came from someone else.</li> </ol>

See <a href="http://en.wikipedia.org/wiki/Public-key_cryptography" rel="nofollow">http://en.wikipedia.org/wiki/Public-key_cryptography</a>

An attacker can bypass this security if they are able to intercept the connection and modify the original client SWF file and either change the public key, or remove the security mechanism entirely. Use TLS or SSL to prevent attackers intercepting the data.

An x.509 certificate is little more than a public key bundled with some meta-data. The standard also specifies a mechanism for validating the certificate, by relying on a certificate authority (CA) (see <a href="http://en.wikipedia.org/wiki/X.509" rel="nofollow">http://en.wikipedia.org/wiki/X.509</a>).

The AS3Crypto library provides (amongst other things), an implementation of RSA, MD5, and an x.509 parser (see <a href="http://code.google.com/p/as3crypto/" rel="nofollow">http://code.google.com/p/as3crypto/</a>).

Here is some code. The signing process entails computing the hash of the data, then signing it with the private key to produce a signature, eg:

var rsa:RSAKey; var md5:MD5; var data:ByteArray = getSWFBytes(); var signature:ByteArray = new ByteArray(); var originalHash:ByteArray; // read private key rsa = PEM.readRSAPrivateKey(private_key); // create the checksum of the original data md5 = new MD5(); originalHash = md5.hash(original); // encrypt the data using the private key rsa.sign(data, signature, original.length);

The data and signature are sent to the client. The client decrypts the signature using the public key stored in the cert and compare it to the computed hash of the data, eg:

var rsa:RSAKey; var md5:MD5; var data:ByteArray = getSWFBytes(); var signature:ByteArray = new ByteArray(); var decryptedHash:ByteArray = new ByteArray(); var clientHash:ByteArray; // load the certificate var cert:X509Certificate = new X509Certificate(public_cert); // get the public key from the cert rsa = cert.getPublicKey(); // decrypt the signature with the public key rsa.verify(signature, decryptedHash, encrypted.length); // create a hash of the data md5 = new MD5(); clientHash = md5.hash(data); // compare the hashes // isEqual compares the bytes in the input byte arrays, it returns true only of all bytes in both arrays match if (isEqual(clientHash, decryptedHash)) trace("signature valid"); else trace("signature invalid")

You can check if the certificate is signed like this:

var store:X509CertificateCollection = new MozillaRootCertificates(); var cert:X509Certificate = new X509Certificate(public_cert); var isValid:Boolean = cert.isSigned(store, store);

You can load the raw SWF bytes like this:

var loader:URLLoader = new URLLoader(); loader.dataFormat = URLLoaderDataFormat.BINARY; loader.addEventListener(Event.COMPLETE, completeHandler); loader.load(new URLRequest(url_of_swf_to_load));

Example x.509 private key (usually created when you apply for a certificate):

-----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQDoKlLzpJeLcoPYQQYPa0diM4zpZ+0rKeRxhx9ssq91DzwAeSmM 7wT03WLiLZkqPt2MS3uNo75zK5RtmjHqF6Ojfs2tbSdlCK5tpisvOAssuq0o5vIz g/MhS2PIijnBtVB9XFSTXxhveKeIq1VgdB2wHW95+zhBF+Z1hsYcNRRFFwIDAQAB AoGAI8wK2EhjmXvBuoFkJtJ6wjiCnKaKmiIueBbGkKMIjLsZnFUSRAnCsOLF0WwI dswUqwIkfdVmkymADFo/IgIdF9hLGNLRskIPKGZWEUC8d5ZJnRg+nuzi2c2msN5u /BvCCgL5/shBhO5KvrPbU/Fbs/k4saCDQZ2EO4HpueRZWGkCQQD6hC0pTfyW4yQT Qr/dY7FhOwdOh/8ewGyXBa9ruOuZqTR23Ya20O8NuF22+NqW9AZl7uioiTZyZkOV jqAckelrAkEA7T9QVdK+QcaQSznrZPJpXlSIDLSBRWjaPKBoypnNTF3y3JkUQE0L iA0c2oUc8D+LCgx9vA0Ai0IzwzrIec+iBQJAJb5YV4rKbalXPBeodKCajv2nwis3 QtjXA4H1xhMcXBBkOSxzKYQdIEIQzIp91JR7ikwOfaX+sAm8UQImGWfadQJAMAb4 KVePQluDDGd+OqJEKF9uZzwHS1jNjSZf8FuwTrxaFMQ8cEPoiLM22xnFYPFMIU2k CnSLXqWZOvVkbhxVTQJAL3xIc5AUbhsEp7ZeeJrkPRv5rCObmLw0+wIaERtMX83b PNM0TpzY6EXk+geTCqudAipYF/A7qn38wpOh+PuuVg== -----END RSA PRIVATE KEY-----

Example cert:

-----BEGIN CERTIFICATE----- MIID4zCCA0ygAwIBAgIJAL7k5X3sCvniMA0GCSqGSIb3DQEBBQUAMIGoMQswCQYD VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTERMA8GA1UEBxMIU2FuIEpvc2Ux FDASBgNVBAoTC2h1cmxhbnQuY29tMRcwFQYDVQQLEw5hczMgY3J5cHRvIGxpYjEY MBYGA1UEAxMPSGVucmkgVG9yZ2VtYW5lMSgwJgYJKoZIhvcNAQkBFhloZW5yaV90 b3JnZW1hbmVAeWFob28uY29tMB4XDTA3MTEwNTA1MjUyOVoXDTA4MTEwNDA1MjUy OVowgagxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMREwDwYDVQQH EwhTYW4gSm9zZTEUMBIGA1UEChMLaHVybGFudC5jb20xFzAVBgNVBAsTDmFzMyBj cnlwdG8gbGliMRgwFgYDVQQDEw9IZW5yaSBUb3JnZW1hbmUxKDAmBgkqhkiG9w0B CQEWGWhlbnJpX3RvcmdlbWFuZUB5YWhvby5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD gY0AMIGJAoGBAOgqUvOkl4tyg9hBBg9rR2IzjOln7Ssp5HGHH2yyr3UPPAB5KYzv BPTdYuItmSo+3YxLe42jvnMrlG2aMeoXo6N+za1tJ2UIrm2mKy84Cyy6rSjm8jOD 8yFLY8iKOcG1UH1cVJNfGG94p4irVWB0HbAdb3n7OEEX5nWGxhw1FEUXAgMBAAGj ggERMIIBDTAdBgNVHQ4EFgQU/XyNp2QghYm3MWOU5YoUoFWcTKMwgd0GA1UdIwSB 1TCB0oAU/XyNp2QghYm3MWOU5YoUoFWcTKOhga6kgaswgagxCzAJBgNVBAYTAlVT MRMwEQYDVQQIEwpDYWxpZm9ybmlhMREwDwYDVQQHEwhTYW4gSm9zZTEUMBIGA1UE ChMLaHVybGFudC5jb20xFzAVBgNVBAsTDmFzMyBjcnlwdG8gbGliMRgwFgYDVQQD Ew9IZW5yaSBUb3JnZW1hbmUxKDAmBgkqhkiG9w0BCQEWGWhlbnJpX3RvcmdlbWFu ZUB5YWhvby5jb22CCQC+5OV97Ar54jAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEB BQUAA4GBABsXUJjiRAz+FeiVq4JMSBWeiiGcXTw+8sNv8SfWaWx3su+AgooKlBn3 nsGKf3BEDdmJCOSgY0+A5Pce9SRoAMhabHKwoLEogrtp2p8vRj2OTMjWBW7ylrxj FvUpFdc8qFaqTtgH6+JiIYllGFlcsSV+6d9fDPaFDZEHjz5GweWJ -----END CERTIFICATE-----

Both examples were taken from as3crypto.

Recommend

  • Are JWTs a secure option for user authentication?
  • CSRF protection techniques
  • When is it necessary to escape double quotes and other characters when inserting them into MySQL dat
  • Issue with parameters in Modelsim
  • CSRF protection - is a JWT and CORS whitelist combination sufficient?
  • Why can't pass only 1 coulmn to glmnet when it is possible in glm function in R?
  • starttls on node.js > 0.4.0
  • How to connect to TLS 1.2 enabled URL with Java [closed]
  • 'SOCK_RAW' option in 'socket' system call
  • synology php ftp_ssl_connect - Call to undefined function
  • PHPMailer is causing 504 timeout error on my Digital Ocean server using nginx
  • Mod_rewrite: Force SSL on specific pages. Add www on none-secure pages
  • PHP OOXML Libraries? [closed]
  • How Can I Prevent Activation For Some ListView Items When The Selection Mode Is MultiChoiceModal?
  • How can I make a right-click behave as a left-click for the purpose of selecting or focusing an obje
  • three.js WebVR example code works on threejs.org but not on my local server
  • Spring Security bcrypt encoding login is not working
  • sudo easy_install for SimpleITK not that easy
  • Changing media screen makes div overlay
  • How to log in to an HTTPS website with Jsoup?
  • Consuming a WCF service in a Java Client using wsHttpBinding
  • How to programatically 'login' a user based on 'remember me' cookie when using j
  • How to autopopulate a field in SugarCRM form
  • Bash if statement with multiple conditions
  • Check for zero lines output from command over SSH
  • nonblocking BIO_do_connect blocked when there is no internet connected
  • Tamper-proof configuration files in .NET?
  • OOP Javascript - Is “get property” method necessary?
  • MailKit: The IMAP server replied to the 'EXAMINE' command with a 'BAD' response
  • Master page gives error
  • Redux, normalised entities and lodash merge
  • Display Images one by one with next and previous functionality
  • Calling of Constructors in a Java
  • Run Powershell script from inside other Powershell script with dynamic redirection to file
  • Traverse Array and Display in markup
  • Transpose CSV data with awk (pivot transformation)
  • Load html files in TinyMce
  • How can I get HTML syntax highlighting in my editor for CakePHP?
  • Why can't I rebase on to an ancestor of source changesets if on a different branch?
  • coudnt use logback because of log4j