677 Commits

Author SHA1 Message Date
Pierre Ossman 06e61fa4cc websockify 0.11.0 2022-12-16 13:11:04 +01:00
Pierre Ossman 4f9d496dfe Use local websockify when building container
It's very surprising to get some external copy of websockify when you
are building an image in your local websockify source tree. Make sure we
are using the local copy of everything.
2022-12-16 13:10:58 +01:00
Pierre Ossman 1979e92f0e Also require all token plugin requirements
Token plugins are technically optional, but if you are installing
websockify via pip then all of these are available anyway. So let's make
things simple for users.
2022-12-16 13:08:23 +01:00
Adam Tilghman d2affc73b5 Insert rebinder at the head of the (possibly empty) LD_PRELOAD pathlist,
required for use cases relying on other preloaded libraries e.g. nss_wrapper.
2022-11-16 16:35:39 -08:00
Pierre Ossman 27ee353401 Don't include default message to send_error()
Python can provide this for us, so avoid duplication.
2022-11-16 15:28:18 +01:00
Pierre Ossman 39c7cb0115 Merge branch 'http_api' of https://github.com/CendioOssman/websockify 2022-11-08 14:29:12 +01:00
Linn Mattsson be7b868518 Remove logging from handle_upgrade()
The logging should be handled directly in send_response() instead, which
is the default of Python's built-in send_response(). Remove this manual
logging to avoid logging the same call twice.
2022-11-08 14:24:46 +01:00
Linn Mattsson 4695f96728 Add new websocket class HttpWebSocket
This class acts as a glue between websocket and http functionality by
taking a 'request_handler' and using its functions for send_response(),
send_header() and end_headers().
2022-11-08 14:24:46 +01:00
Linn Mattsson 832ae23f00 Make websocket's API more intuitive
Functions connect() and accept() are using http functionality, like
sending requests and headers. Let's create separate functions with more
intuitive names for these calls. This allows subclasses to override
these functions, as well as makes the code easier to understand at a
glance.
2022-11-08 14:05:46 +01:00
Jokin c123bfbbff Add requests module 2022-10-20 11:28:34 +00:00
Manoj Ghosh 70579756f3 expose --file-only option to disable dir listing 2022-10-18 04:10:44 -07:00
Pierre Ossman e9c80aa32a Merge branch 'master' of https://github.com/msnatepg/websockify 2022-10-10 10:13:01 +02:00
Maximilian Sesterhenn caef680fff ensure that queues are empty when closing connections 2022-10-07 14:24:53 +02:00
Pierre Ossman 7133f85df6 Merge branch 'verbose_logging' of https://github.com/javicacheiro/websockify 2022-08-18 11:11:22 +02:00
Samuel Mannehed 33910d758d Merge pull request #521 from javicacheiro/fix_jwcrypto
Tests break with jwcrypto>=1.3
2022-05-26 15:59:39 +02:00
Javier Cacheiro 0f17500348 Support for jwcrypto>=1.3 2022-05-25 12:40:29 +02:00
Pierre Ossman 4b194636e2 Merge branch 'dockerfile' of https://github.com/javicacheiro/websockify 2022-05-11 14:23:40 +02:00
Javier Cacheiro ffa31d6c2c When using verbose set root log level to DEBUG 2022-05-03 09:58:50 +02:00
Javier Cacheiro dec26a6a2d Docker support 2022-04-22 13:21:57 +02:00
Pierre Ossman d96ecf0859 Add more alternatives to usage string
If you use a token plugin, or a Unix socket target, then you should no
longer specify a target on the command line. Add these to the usage
string to make this clear.
2022-04-22 10:19:54 +02:00
Pierre Ossman d0ad4a1b2a Merge branches 'use_logging' and 'fix_logging_configuration' of https://github.com/javicacheiro/websockify 2022-04-14 09:15:21 +02:00
Javier Cacheiro e1f903b9e8 Apply configuration to the root logger 2022-04-13 17:02:05 +02:00
Javier Cacheiro 62ac4aeb03 Use logging instead of directly printing messages to sys.stderr 2022-04-13 16:12:31 +02:00
Pierre Ossman e4cff3746d Explicitly install old wrapt on Python 3.4
Something is broken in pip so it installs a wrapt that doesn't support
Python 3.4. Work around this by manually request a version that is known
to work.
2022-04-13 12:50:25 +02:00
Javier Cacheiro d5e8d709d7 Add tests for TokenRedis 2022-04-12 10:58:42 +02:00
Pierre Ossman dc345815c0 Use RSA-OAEP instead of RSA1_5 for jwt tests
The latest version of jwcrypto has disabled RSA1_5 by default, making
the tests fail.
2021-07-23 09:38:58 +02:00
Pierre Ossman 71d55fcaa8 Fix bad classifiers array 2021-07-22 17:20:45 +02:00
Pierre Ossman 1c35fdd72b websockify 0.10.0 2021-07-22 17:11:08 +02:00
Pierre Ossman eca301c05b Fix patching of open() for Python 3.4
It doesn't handle builtins automatically, so follow the recommendations
from that time.
2021-05-03 14:34:07 +02:00
Pierre Ossman b9b269c73f Add unit test for token file with tab 2021-04-16 13:02:07 +02:00
Pierre Ossman da130946eb Merge branch 'sisou/split-tokens-tab' of https://github.com/sisou/websockify 2021-04-16 13:00:36 +02:00
Pierre Ossman 100a776409 Add unit tests for ReadOnlyTokenFile 2021-04-16 12:59:17 +02:00
Pierre Ossman 984dcc62d3 Move JWT token plugins tests to separate file
Let's try to match the test units with the modules we have.
2021-04-16 11:27:56 +02:00
Samuel Mannehed c5d365dd1d Merge pull request #479 from llopisdon/patch-1
Update README.md
2021-03-22 09:23:15 +01:00
Don E. Llopis 27e0ce71ed Update README.md
Fixed typo and clarified sentence.
2021-03-20 10:17:55 -04:00
Pierre Ossman 24c3f75ede Remove setuptools version restriction
We're fine with current versions now.
2021-02-08 15:51:34 +01:00
Pierre Ossman 8b724074e0 Use older PROTOCOL_SSLv23 instead of PROTOCOL_TLS
We need to support Python older than 3.6, so use the older name.
2021-02-08 15:47:29 +01:00
Pierre Ossman 55f1fe2603 Explicitly include "six" for jwt tests
It is not properly listed as a dependency for jwcrypto, so we need to
pull it in manually.
2021-02-08 15:46:43 +01:00
Pierre Ossman f1e33fa4c7 Use older numpy for older Python versions
The latest version refuses to run on anything older than Python 3.7.
2021-02-08 15:33:37 +01:00
Pierre Ossman 72704b3fe8 Update classifiers to just Python 3
We no longer support anything older than Python 3.4.
2021-02-08 14:55:49 +01:00
Pierre Ossman 4afdcb00ab Update references in egg manifest
We changed things when we purged all the non-Python stuff out of the
tree.
2021-02-08 14:55:15 +01:00
Pierre Ossman 982e475936 Run all tests even on failure
Issues might be specific to certain versions of Python, so let all tests
run.
2021-02-08 14:42:41 +01:00
Pierre Ossman 6012052686 Use Ubuntu 18.04 for tests
We want to test on Python 3.4, which requires us to use an older Ubuntu
image for tests.
2021-02-08 11:11:39 +01:00
Pierre Ossman e4e85f8082 Replace Travis with Github actions 2021-02-08 11:02:48 +01:00
Pierre Ossman f7b0867471 Merge branch 'fix467_redis' of https://github.com/PexMor/websockify 2021-02-08 10:42:01 +01:00
PexMor 9dab8b360b add details on format of redis and leave port as number 2021-02-07 20:39:02 +01:00
Alexander E. Patrakov 4afafcd152 Simplify Windows instructions
Instead of a Websockify-specific tool that needs to be compiled, and
that doesn't work on Windows 10 anyway (the service takes forever to
start), let's switch to the industry standard SrvAny tool. This also
gets rid of .Net Framework requirement and lets one run modern
versions of Websockify easily.
2021-01-30 17:11:20 +05:00
Pierre Ossman b22a6b0ce0 Add unit tests for jwt token time checks 2021-01-29 13:11:07 +01:00
Pierre Ossman 980237c9cd Merge branch 'new_branch' of https://github.com/jprietove/websockify 2021-01-29 13:10:49 +01:00
Pierre Ossman fadb25e026 Use assertRaises() as a context manager
Makes the code a lot easier to read.
2021-01-29 13:10:16 +01:00
Pierre Ossman 3f17696dc6 Use patch() as a decorator in tests
Cleaner and more robust.
2021-01-29 13:09:19 +01:00
Pierre Ossman a82eb10b48 Remove Python version check
We require Python 3 now, so no need for this check.
2021-01-29 12:58:26 +01:00
Javier Prieto 1f618c8f41 Added JWT nbf, not before 2021-01-27 16:50:19 +01:00
Javier Prieto e9367b03be Added exp claim for JWT token 2021-01-27 15:16:08 +01:00
Tim Gates adc278657a docs: fix simple typo, acccept -> accept
There is a small typo in README.md.

Should read `accept` rather than `acccept`.
2020-12-25 20:37:15 +11:00
Pierre Ossman 108f993eb3 Explicitly request Python 3
It varies between systems if /usr/bin/python is Python 2.x or Python
3.x. Since we now only work with Python 3.x we should be more explicit
in our scripts and documentation.
2020-12-15 16:10:43 +01:00
Pierre Ossman 33710b3972 Use frombytes() instead of fromstring()
Both the Python library and NumPy have changed the names of these
functions to better match the new bytes data type it actually uses.
2020-12-14 16:08:16 +01:00
Pierre Ossman 96eda1a5c7 Remove support for older Python
All active distributions should now support at least Python 3.4, so
let's clean things up by removing older compatibility code.
2020-12-14 13:48:54 +01:00
Pierre Ossman e80739b296 Add more search paths for rebind.so
If we're run as a module then sys.argv[0] will be the main module, not
some startup script.
2020-12-04 13:57:21 +01:00
Samuel Mannehed 4c2edaabc2 Merge pull request #459 from nwtgck/patch-1
fix a typo
2020-11-18 09:15:42 +01:00
Ryo Ota d2155697fc fix a typo 2020-11-18 08:53:09 +09:00
JasonYang 2b44803f83 fixed a bug in the function of send_frames. 2020-11-10 13:14:54 +01:00
Pierre Ossman 01ef6a6a55 Require same arguments on insufficient socket space
This matches the behaviour of SSLSocket, which we are trying to mimic.
It also closely matches the behaviour of normal Socket which can be
assumed to not have sent anything if an error occurs. We might actually
send some data, but the caller cannot really see that and must call us
again as if no data was sent.
2020-09-30 14:58:19 +02:00
Pierre Ossman 6caf23c067 Add type checking when sendning data
We use this in various ways so add an early check to make things clear
in case anything is called incorrectly.
2020-09-30 14:53:19 +02:00
Pierre Ossman d72ace2ae6 Allow sending empty messages
This is perfectly valid in the protocol, and may be meningful to some
applications. However send() is still stream oriented so it will ignore
an empty buffer.
2020-09-30 14:51:07 +02:00
Samuel Mannehed 536a548db5 Merge pull request #441 from RangeForce/python-gitignore
Add build and dist directories to .gitignore
2020-09-02 02:19:12 +02:00
Chris Kerr 997b3897e7 Add build and dist directories to .gitignore 2020-09-01 10:26:46 +03:00
Samuel Mannehed 7d4841c49a Merge pull request #440 from gamtiq/patch-1
Fix a typo in README
2020-08-25 16:51:00 +02:00
Denis Sikuler 9851dd9012 Fix a typo in README 2020-08-24 15:36:35 +03:00
Pierre Ossman 9b1780f068 Fix bad reset of fragmented frame
The Python 2/3 binary data type compatibility hack was backwards here.
2020-08-21 10:58:55 +02:00
Pierre Ossman e5b6dfe17f Merge branch 'sisou/fix-print-statement' of https://github.com/sisou/websockify 2020-08-21 10:51:37 +02:00
Pierre Ossman 992e09eac4 Convert tests from mox to mock
mox is deprecated upstream in favour of mock
2020-08-21 10:50:11 +02:00
Sören Schwert 663b39cd38 Split token file by any whitespace after the colon, not just a space
With the current parser logic, only tokens and servers that are separated by _exactly_ a colon and a space `: ` are detected as tokens. But when formatting one's token file with tabs, this breaks.

This commit changes the split characters to be a regular expression that matches all forms of whitespace, including spaces and tabs.
2020-07-28 14:40:42 +02:00
Sören Schwert 57be17d7f5 Convert old print statement into function
For Python 3 compatibility.
2020-07-28 14:35:49 +02:00
Pierre Ossman 86a20b23f5 Update test requirements
Travis are dropping older Python environments, so update things to
something that reflects what current distributions are using (e.g. Red
Hat Enterprise Linux 7).
2020-04-08 09:18:09 +02:00
Feng Ye 7bd955a379 Add UnixDomainSocketDirectory token plugin 2020-03-18 10:40:18 +08:00
Pierre Ossman 6d48b1507e Make sure port is a simple string (again)
The redis token plugin also needs to make sure the port string isn't
unicode for compatibility with Python 2.x.
2020-02-27 15:55:35 +01:00
Pierre Ossman 76897b5093 Log connection errors better 2020-02-27 15:54:29 +01:00
Samuel Mannehed 4ecff119c4 Merge pull request #405 from andersk/shell
run: Fix shell scripting bugs
2019-09-26 08:42:17 +02:00
Anders Kaseorg 5052f823d7 run: Fix shell scripting bugs
* Use double quotes around `"$@"` to fix invocation with arguments
  including spaces.
* Use double quotes around `"$(dirname "$0")"` to fix invocation
  inside a directory path including spaces.
* Use `set -e` to abort in case `cd` fails.
* Use `exec` to avoid forking an unnecessary wrapper process.
* Skip an unnecessary `cd` → `pwd` → `cd` dance, just use `cd`.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2019-08-17 11:39:46 -07:00
Pierre Ossman 654cbac77e websockify 0.9.0 2019-08-13 13:56:31 +02:00
Pierre Ossman 4ed68eab97 Update release instructions 2019-08-13 13:56:31 +02:00
Pierre Ossman 312a6d200c Mark package description as being Markdown
PyPi is now very picky about the format and will not accept things
blindly.
2019-08-13 13:53:16 +02:00
Samuel Mannehed 53004a071d Remove javascript files from setup.py
The js implementation of websockify has been split into a different
repository, this means that these files are no longer present here.
2019-07-14 23:22:10 +02:00
Samuel Mannehed 1553fa791e Merge pull request #362 from CendioOssman/split
Remove all non-Python stuff from the tree
2019-07-12 13:44:22 +02:00
Pierre Ossman 6d82536d2b Fix all old kanaka links
We now have our own organisation for noVNC and friends.
2019-07-04 13:11:13 +02:00
Pierre Ossman 368ec2c06e Remove all non-Python stuff from the tree
We're splitting the repository into multiple ones. This one will
only retain the Python stuff (and rebind, used by websocketproxy).

Only once license is needed after this, so use the standard COPYING
filename.
2019-07-04 11:27:40 +02:00
Pierre Ossman 60acf3cd3c Use direct javascript in test files
Avoid relying on our own modules as we are about to split things up.
2019-07-03 15:56:25 +02:00
Pierre Ossman b46fab5608 Make sure the port is a simple string
getaddrinfo() gladly allows unicode for the host, but the port must
be in ascii (e.g. "https"). Make sure this is properly converted
before we pass it on.

Patch by @caderize on GitHub.
2019-07-03 12:29:02 +02:00
Pierre Ossman 6a268a09b6 Use safer method to get base directory
realpath isn't available on older systems, so use a safer approach
using just very basic commands.
2019-06-24 15:38:52 +02:00
Pierre Ossman 1f717e83af Remove information on building Python SSL module
Even old systems have this module these days, so these instructions
only serve to confuse people.
2019-06-24 15:32:21 +02:00
Pierre Ossman 60413587ac Merge branch 'patch-1' of https://github.com/Hyask/websockify 2019-06-17 15:21:14 +02:00
Skia 4f6a82159c run: invoke websockify through 'python -m' 2019-06-17 15:04:43 +02:00
Skia f21a7d33a2 Add a __main__.py file for invocation as a module
This file allows an easy invocation of websockify as a module, which is handy when running into shebang issues (https://github.com/pypa/virtualenv/issues/596).
With this patch, `python -m websockify ...` has just the same behavior as `./run ...`.
2019-06-13 17:16:25 +02:00
Pierre Ossman b382c4f6a7 Use Ubuntu Trusty (14.04) for Travis
Python 2.6 is not available in the newer environment, so make sure
we're getting the one we need for now.
2019-06-13 13:38:43 +02:00
Pierre Ossman 01a184f4a9 Make TokenRedis optional
Most installations will not have redis or simplejson installed, so
avoid having them as a hard requirement unless actually using the
TokenRedis plugin.
2019-05-24 12:56:23 +02:00
Giuseppe Corbelli 70911c6d6e [websocketproxy] Fixed base class call to process_request() when using
ThreadingMixIn
2019-05-15 14:58:47 +02:00
Pierre Ossman c1edd7818d Merge branch 'master' of https://github.com/PexMor/websockify 2019-05-09 15:51:45 +02:00
PexMor ff3fdd149d novnc redis backed token_plyugins.py 2019-04-29 20:32:04 +02:00
Pierre Ossman be9823bf93 Use client IP in logs, not host
This is the more common behaviour, and it is also more reliable as
it may require some time to look up hostnames and they may change
over time.
2019-04-25 10:05:14 +02:00
Pierre Ossman e4658ada2e Re-enable Windows support
It works well enough now with the recent fixes and a modern Python.
2019-04-02 17:04:19 +02:00
Pierre Ossman 85074b6eb5 Use ThreadingMixIn for the simple server
ForkingMixIn isn't available on Windows. This is the simple server
without features, so use ThreadingMixIn to keep things consistent.
2019-04-02 17:03:08 +02:00
Pierre Ossman d751ec44a8 Allow main script to be imported
We should only start the server if we are the main module, and not
imported some other way. This is important for multiprocessing to
work correctly on Windows.
2019-04-02 17:02:08 +02:00
Samuel Mannehed 6e09ec2548 Merge pull request #382 from Nevon/ssl-key-passphrase
Add option for cert key password
2019-03-13 13:34:03 +01:00
Tommy Brunn 92cb3d8355 Rename certificate key password option 2019-03-04 09:31:01 +01:00
Tommy Brunn 0163e4060b Add option for cert key password 2019-03-02 17:21:28 +01:00
Samuel Mannehed c136ea2d34 Merge pull request #380 from totaam/master
fix handling of "code"
2019-02-24 22:43:21 +01:00
totaam a348b8bf76 fix handling of code: invalid unpacking, undefined variable in error path, missing argument 2019-02-23 12:37:16 +07:00
UXabre f2031eff05 Added JWT/JWS/JWE tokens capability 2019-02-15 03:45:57 -05:00
Pierre Ossman f0bdb0a621 Handle connection failures
The service we're proxying to might not be responding. Make sure
this is caught sanely and we get nice logging and messages back to
the client.
2018-10-23 16:31:57 +02:00
Pierre Ossman 8eb5cb0cdc Explicitly deny text messages
We can't really handle them, but let's respond with an explicit error
rather than "unknown opcode".
2018-10-23 16:31:07 +02:00
Pierre Ossman 6a9e446f8e Avoid : in recording file names
That character is not legal in Windows file names, so make sure we
avoid it when creating recording files.
2018-10-16 16:10:37 +02:00
Pierre Ossman 7abd7ac4a9 Merge branch 'master' of https://github.com/josedpedroso/websockify 2018-09-10 16:39:32 +02:00
josedpedroso 7e29a36f6a Syslog now RFC 5424 compliant and properly identified. 2018-08-28 19:52:47 +01:00
Pierre Ossman be5d30ad25 Change WebSocket request handler to a mix-in
We can't get the inheritence right in non-trivial cases as a regular
base class, so change it to be a mix-in that is to be combined with
one of the existing request handlers from the Python library.
2018-08-15 17:07:37 +02:00
josedpedroso d80c607cb6 Port no longer included in token when using --host-token 2018-07-12 20:21:08 +01:00
Pierre Ossman 6ba82d371b Merge branch 'master' of https://github.com/josedpedroso/websockify 2018-07-11 13:37:17 +02:00
josedpedroso 8cb89d2340 Clarified usage of --host-token and added a section about installing Python websockify in the README. 2018-07-06 14:33:13 +01:00
Tomasz Barański 7c816eb207 Added command line options for minum SSL version and SSL ciphers
--ssl-version takes two possible values (tlsv1_1, tlsv1_2). Defaults
to tlsv1_1.
--ssl-ciphers takes allowed ciphers in the same format as
`openssl ciphers`.

Added options for 1.3 and the default ssl config
2018-07-05 21:55:29 +02:00
Tomasz Barański 51ad14d16c Enable setting SSL ciphers and SSL options
The change adds two options to WebSockifyServer. The first is a list of
SSL ciphers. The second is SSL options (intended use is to force a
specific TLS version).

Those two options allow for greater security of WebSocket Proxy.
2018-07-05 21:54:20 +02:00
josedpedroso 08b402d111 Added a couple of paragraphs about plugins and the new options to the README. 2018-07-05 00:55:12 +01:00
josedpedroso af85184e28 Added --host-token to allow choosing target by hostname. 2018-07-05 00:54:19 +01:00
josedpedroso 44bb213a72 Improved --help. 2018-07-05 00:53:09 +01:00
josedpedroso 525bfa6bae Added syslog support.
Reworked logging setup.
2018-07-05 00:50:48 +01:00
josedpedroso 8964adf111 Added --web-auth option to require authentication to access the webserver.
BasicHTTPAuth plugin now issues 401 on bad credentials to allow the user to try again.
2018-07-05 00:48:08 +01:00
Pierre Ossman 38b77714a9 Make recording Python 3 compatible
Python 3's bytes objects require a bit more care to get in to the
output format we need.
2018-04-05 16:07:09 +02:00
Giannis Kosmas 3646575c99 Remove policyfile from deps 2018-03-20 14:35:06 +02:00
Pierre Ossman e5e1dcef79 Clean up after request handler
We need to call the base class after a request is finished in
order to clean up things properly. E.g. closing the socket file
descriptor.
2018-03-19 15:31:34 +01:00
Pierre Ossman 193c7e6181 Merge branch 'filedescriptor-fix' of https://github.com/pesintta/websockify 2018-03-05 16:23:44 +01:00
Pierre Ossman f750df7bdb Merge branch 'binary-websockets' of https://github.com/pesintta/websockify 2018-03-05 16:21:57 +01:00
Pierre Ossman 3b2a0a5884 Make sure ping/pong data is in the correct type
For Python 3 we need to make sure the data payload is bytes, not str.
2018-02-28 10:58:25 +01:00
Antti Seppälä e7af149cd1 C websockify: Fix file descriptor leak
After fork() the parent process has a copy of clients file descriptor which
needs to be closed by the parent to prevent a descriptor leak.
2018-02-17 19:32:11 +02:00
Samuel Brian 4202818be9 C websockify: support for binary websocket protocol with HyBi/RFC 6455.
The server prefers binary over base64 encoding, given a choice. This is required as noVNC no longer supports base64 encoding.
2018-02-17 18:04:48 +02:00
Antti Seppälä 3a03e3c59d C websockify: use openssl base64 encode/decode functions
b64_pton and b64_ntop functions are not portable and cannot be found in
all C library implementations (e.g. uClibc, musl).

Since c-websockify already has explicit dependency to openssl it can be
used to replace b64_pton/ntop with versions that are portable without
introducing too much additional code or dependencies.
2018-02-11 13:17:11 +02:00
Antti Seppälä 7235c9765e C websockify: Load entire certificate chain
Instead of single certificate in one file it is sometimes customary to
chain multiple certificates into the same file. This is common practice
for CAs like letsencrypt that are providing intermediate certificates.

This patch switches loading of only one certificate to loading whole chain
of certificates.

The effects can be seen with e.g. the following command:

openssl s_client -showcerts -connect websockify-hostname:8080

Before the change the verify fails:

Certificate chain
 0 s:/CN=websockify-hostname
   i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3

After the change the verify passes:

Certificate chain
 0 s:/CN=websockify-hostname
   i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
 1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
   i:/O=Digital Signature Trust Co./CN=DST Root CA X3
2018-02-03 10:18:06 +02:00
Pierre Ossman 3d20cabf40 Fix handling of closed proxy socket
Regression caused by a29946e9. We were no longer detecting a cleanly
closed proxy socket. This is not a WebSocket, but an ordinary one,
so we should be checking for "" rather that None.
2018-01-25 15:46:41 +01:00
Aaron C. de Bruyn 46406c76e7 Add recording feature to websockify.js. Closes GH-249 2017-11-16 18:37:34 -08:00
Pierre Ossman 6b1d42e643 Merge branch 'empty-message' of https://github.com/andersk/websockify 2017-11-13 10:44:57 +01:00
Anders Kaseorg b0df514344 Clarify that WebSocket.{recv,recvmsg} may return empty messages
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2017-11-13 04:13:48 -05:00
Anders Kaseorg a29946e978 Do not confuse an empty message with a closed connection
Fixes #312.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2017-11-10 06:26:48 -05:00
Anders Kaseorg 3c1655322d Do not use base except: clauses
https://docs.python.org/2/howto/doanddont.html#except

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2017-11-10 05:48:20 -05:00
wention ade9d61c22 fixed: ssl call error at function load_cert_chain.
If option '--key' is not specified. 'WebSockifyServer class' will
       inital self.key as empty string. but ssl load_cert_chain function
       will raise error 'no such file' with keyfile param empty string.
2017-11-09 16:13:15 +08:00
Pierre Ossman 8b2a949276 Merge branch 'ssl_clientdn_validation' of https://github.com/hoehermann/websockify 2017-10-30 13:12:18 +01:00
Pierre Ossman 5f7d28aeb6 Only start termination process once
We can't deal with the exception once we've started to shut down so
make sure it's only raised once.
2017-10-27 08:41:32 +02:00
Pierre Ossman 0a6e0c2d87 Don't log clients that don't send any request
They just fill up the logs with confusing data.
2017-10-27 08:25:35 +02:00
Hermann Höhne 914609fb5f Added SSL-certificate-based client authentication.
* Incorporates #190 without breaking compatibility towards old Python versions.
* A new plugin allows authenticating clients by the "common name" defined in their certificate.
* Added manual for certificate-based client authentication, including hints to which Python versions allow client certificate authentication.
* Adjusted test to work with new ssl.create_default_context.
2017-10-26 15:17:11 +02:00
Pierre Ossman abcf2cd4d4 Merge branch 'patch-1' of https://github.com/tillz/websockify 2017-10-18 16:36:43 +02:00
Pierre Ossman e69d4a4546 Properly declare websocket functions in header 2017-10-18 16:35:52 +02:00
Pierre Ossman 93842aa798 Avoid implicit int type 2017-10-18 16:35:42 +02:00
Pierre Ossman 89bbb64145 Include string.h where needed 2017-10-18 16:35:30 +02:00
Pierre Ossman 814279b83b Merge branch 'master' of https://github.com/leeyiw/websockify 2017-10-18 16:29:37 +02:00
Pierre Ossman 414d1d8b44 Merge branch 'fix-cygwin' of https://github.com/r1b/websockify 2017-10-18 16:25:37 +02:00
Giannis Kosmas 99198cface Send Content-Type headers with static files
Fixes a problem that occurs in Chrome 61 where the following error message appears in the console:

'Failed to load module script: The server responded with a non-JavaScript MIME type of "".
Strict MIME type checking is enforced for module scripts per HTML spec.'
2017-10-12 19:28:30 +03:00
Pierre Ossman 61879b175c Better error message for problems in token file 2017-10-10 10:10:10 +02:00
Pierre Ossman 0506b3431f Fix sub protocol handling when no protocol is specified
Some browsers are being difficult and won't let us pass on
undefined values for the protocols argument.
2017-09-04 14:11:55 +02:00
Pierre Ossman 5e19bc3f96 Merge branch 'master' of https://github.com/michalsrb/websockify 2017-08-14 17:12:19 +02:00
Michal Srb 2c0e8cb8f4 Fix inetd mode on Python 2.
In python 2 the ssl.wrap_socket doesn't work on sockets created using socket.fromfd.
The workaround is to wrap the socket returned by socket.fromfd into another socket
object using the private _sock constructor parameter.
2017-08-14 16:59:54 +02:00
Michal Srb 867cb21ba0 Add support for inetd.
With the --inetd parameter, websockify doesn't require the source_addr and
source_port paramters and it expects that stdin is already opened and listening
socket.

This way websockify can be used with (x)inetd or as a systemd socket-activated
service.
2017-08-14 16:59:54 +02:00
Pierre Ossman bfd7394cae Remove stray comma in signal handler setup
It was causing the handlers to be set up improperly.
2017-08-14 16:51:55 +02:00
Pierre Ossman 518e6e0e56 Prevent startup on Windows
There's way too many things to fix before this has any chance of working.
2017-06-15 15:18:29 +02:00
Solly Ross ddcec961ec Work around lack of SIGCHLD on Windows
This only enables the SIGCHLD handler if SIGCHLD
exists, such that platforms without SIGCHLD (such
as windows) can still run websockify natively.

See #108
2017-06-15 14:23:29 +02:00
Pierre Ossman d029e451cf Merge branch 'test_websockifyserver_python3.6' of https://github.com/zmedico/websockify 2017-05-24 16:14:33 +02:00
Zac Medico a45b960983 test_websockifyserver: add send_error stub
The socket.sendall method is called indirectly via calls
to the python3.6 BaseHTTPRequestHandler.send_error method
which is called by both the Web*RequestHandler classes as
shown below:

======================================================================
ERROR: test_list_dir_with_file_only_returns_error (test_websockifyserver.WebSockifyRequestHandlerTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_websockifyserver.py", line 115, in test_list_dir_with_file_only_returns_error
    FakeSocket('GET / HTTP/1.1'), '127.0.0.1', server)
  File "websockify/websockifyserver.py", line 94, in __init__
    WebSocketRequestHandler.__init__(self, req, addr, server)
  File "websockify/websocketserver.py", line 34, in __init__
    BaseHTTPRequestHandler.__init__(self, request, client_address, server)
  File "/usr/lib64/python3.6/socketserver.py", line 696, in __init__
    self.handle()
  File "websockify/websockifyserver.py", line 293, in handle
    SimpleHTTPRequestHandler.handle(self)
  File "/usr/lib64/python3.6/http/server.py", line 418, in handle
    self.handle_one_request()
  File "websockify/websocketserver.py", line 46, in handle_one_request
    BaseHTTPRequestHandler.handle_one_request(self)
  File "/usr/lib64/python3.6/http/server.py", line 406, in handle_one_request
    method()
  File "websockify/websocketserver.py", line 58, in _websocket_do_GET
    self.do_GET()
  File "websockify/websockifyserver.py", line 259, in do_GET
    SimpleHTTPRequestHandler.do_GET(self)
  File "/usr/lib64/python3.6/http/server.py", line 636, in do_GET
    f = self.send_head()
  File "/usr/lib64/python3.6/http/server.py", line 679, in send_head
    return self.list_directory(path)
  File "websockify/websockifyserver.py", line 263, in list_directory
    self.send_error(404, "No such file")
  File "/usr/lib64/python3.6/http/server.py", line 470, in send_error
    self.end_headers()
  File "/usr/lib64/python3.6/http/server.py", line 520, in end_headers
    self.flush_headers()
  File "/usr/lib64/python3.6/http/server.py", line 524, in flush_headers
    self.wfile.write(b"".join(self._headers_buffer))
  File "/usr/lib64/python3.6/socketserver.py", line 775, in write
    self._sock.sendall(b)
AttributeError: 'FakeSocket' object has no attribute 'sendall'

======================================================================
ERROR: test_normal_get_with_only_upgrade_returns_error (test_websockifyserver.WebSockifyRequestHandlerTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_websockifyserver.py", line 101, in test_normal_get_with_only_upgrade_returns_error
    FakeSocket('GET /tmp.txt HTTP/1.1'), '127.0.0.1', server)
  File "websockify/websockifyserver.py", line 94, in __init__
    WebSocketRequestHandler.__init__(self, req, addr, server)
  File "websockify/websocketserver.py", line 34, in __init__
    BaseHTTPRequestHandler.__init__(self, request, client_address, server)
  File "/usr/lib64/python3.6/socketserver.py", line 696, in __init__
    self.handle()
  File "websockify/websockifyserver.py", line 293, in handle
    SimpleHTTPRequestHandler.handle(self)
  File "/usr/lib64/python3.6/http/server.py", line 418, in handle
    self.handle_one_request()
  File "websockify/websocketserver.py", line 46, in handle_one_request
    BaseHTTPRequestHandler.handle_one_request(self)
  File "/usr/lib64/python3.6/http/server.py", line 406, in handle_one_request
    method()
  File "websockify/websocketserver.py", line 58, in _websocket_do_GET
    self.do_GET()
  File "websockify/websockifyserver.py", line 257, in do_GET
    self.send_error(405, "Method Not Allowed")
  File "/usr/lib64/python3.6/http/server.py", line 470, in send_error
    self.end_headers()
  File "/usr/lib64/python3.6/http/server.py", line 520, in end_headers
    self.flush_headers()
  File "/usr/lib64/python3.6/http/server.py", line 524, in flush_headers
    self.wfile.write(b"".join(self._headers_buffer))
  File "/usr/lib64/python3.6/socketserver.py", line 775, in write
    self._sock.sendall(b)
AttributeError: 'FakeSocket' object has no attribute 'sendall'
2017-05-22 07:27:28 -07:00
Sam Frances 141ba0088e Change logging of URL to be compatible with both old and new versions
of ws
2017-05-18 10:08:54 +01:00
Sam Frances 3e17187216 Fix bug caused by upgrade to ws version 3 2017-05-17 15:37:07 +01:00
Pierre Ossman f3a0ce06a9 Add unittests for ping() and pong() 2017-04-19 13:30:47 +02:00
Pierre Ossman 8ea96a503a Handle ping/pong without payload properly
It has to be a data buffer, not None.
2017-04-19 13:30:10 +02:00
Felix J. Ogris 8f85c9661f typo in ping() and pong() 2017-04-12 18:01:13 +02:00
Pierre Ossman 5b7f7224ed Don't try to install Flash handling code
The actual code was removed in 10e13d7.
2017-03-10 12:46:45 +01:00
Pierre Ossman 61b1b8aef7 Remove base64.js from setup.py
Overlooked in the removal of base64.js in 4099949.
2017-03-09 10:21:29 +01:00
Pierre Ossman 600f4e154c Avoid assertIn for Python 2.6 compatibility
It was added in 2.7, but we want to support older Python a while
longer.
2017-02-09 10:38:53 +01:00
Pierre Ossman df317822d6 Be backwards compatible with older websockify clients
They will specify a sub-protocol, and the specification requires
us to choose one of the specified protocols.
2017-02-08 16:06:14 +01:00
Pierre Ossman c7bde00a4e Force choice of sub-protocol
The WebSocket standard require us to choose one of the protocols
supported by the client. Enforce this with a specific check in the
base class rather than relying on generous clients.
2017-02-08 16:05:16 +01:00
Pierre Ossman 94783ea0cd Remove --auto-pong argument
The underlying code has been removed, so remove the argument
as well.
2017-02-07 15:38:07 +01:00
Pierre Ossman 795552e418 Update websock.js description 2017-02-03 17:02:27 +01:00
Pierre Ossman 40238b00b6 Don't delay flushing
The native WebSocket is in a much better position to do queue
management than us. Many callers also failed to notice this part
of the API, causing stalls.
2017-02-03 17:00:15 +01:00
Pierre Ossman 3f8f301d7f Update websock.js from noVNC
Sync with noVNC as of commit ae510306b5094b55aa08a2a0d15a151704f70993.

The main change is to make it a more proper object that you can
instantiate multiple times.
2017-02-03 16:59:54 +01:00
Pierre Ossman 10e13d7a7e Remove last bits of Flash WebSocket emulation
We require native support from the browsers now.
2017-02-03 16:09:08 +01:00
Pierre Ossman e47591f4aa Split out basic WebSocket server template 2017-02-01 08:33:07 +01:00
Pierre Ossman 8a69762249 Separate out raw WebSocket protocol handling 2017-02-01 08:22:27 +01:00
Pierre Ossman 4099949984 Remove Base64 support
This is an older protocol used before browsers got native
support for Websockets.
2017-02-01 08:09:53 +01:00
Pierre Ossman 56a4ccbf74 Assume Python 2.6+ modules are always present
No relevant distribution has anything older anymore
2017-02-01 08:09:53 +01:00
Pierre Ossman 30942f12d3 Close connection after Websocket handshake
Otherwise we might misinterpret trailing binary data as a second
HTTP request. This happens when we return from the handler with
data still queued up in the socket.
2017-01-19 14:53:15 +01:00
Solly Ross cb1508fa49 Merge pull request #251 from thomasgoirand/master
TCP_KEEPCNT doesn't exist in non-linux
2016-10-10 15:53:40 -04:00
Thomas Goirand 325e4efe00 TCP_KEEPCNT doesn't exist in non-linux
The TCP_KEEPCNT option for sockets only work with the Linux kernel,
this isn't available for example in FreeBSD and Hurd, which makes the
package fail to build on these platforms. See Debian bug here:

https://bugs.debian.org/840035
2016-10-10 12:06:49 +02:00
Solly Ross 72ce5c1ae8 Merge pull request #228 from jrziviani/master
Enable unix socket to work with token plugin
2016-06-30 16:54:35 -04:00
Solly Ross 7d5d73873a Merge pull request #239 from javacruft/mox3
Switch test dependency to mox3
2016-06-30 16:40:03 -04:00
James Page 156b08ae68 Switch test dependency to mox3
mox is pretty much unmaintained these days, however the OpenStack
project are actively maintaining mox3 (a Python 3 compatibile fork
with some other improvements).

websockify seems quite happy to use mox3 instead, so switch the
test dependency and associated imports to use mox3.
2016-06-30 09:59:50 +01:00
samhed f23780eb42 Disable Nagle for proxied connections
Most of the proxy stuff will be latency sensitive traffic so we
disable Nagle because it introduces delays.
2016-06-02 14:45:51 +02:00
Gernot Tenchio 192ec6f5f9 C websockify: free memory after failed handshake
Conflicts:
	other/websocket.c
2016-04-22 12:04:31 -05:00
Solly Ross 1f132f9d84 Update to 0.8.0
See CHANGES.txt for more information
2016-02-18 14:11:15 -05:00
Solly Ross 4e6938e9c2 Merge pull request #226 abhishekkekane/bug/138
Make websockify respond to SIGTERM
2016-02-18 13:43:30 -05:00
Abhishek Kekane 68b1587ada Make websockify respect SIGTERM
Child processes were not terminated when the parent websockify
was killed.

This commit makes websockify send a SIGTERM to all active children
when the parent process is terminated.

Fixes #138
2016-02-18 13:42:53 -05:00
Jose Ricardo Ziviani 7f8baf54e1 Enable unix socket to work with token plugin
This commit adds support to unix sockets in the token plugin, thus it is
possible to have a token files like:

  token: unix_socket:/path/to/socket_file

A single websockify instance will be able to handle multiple sockets.

Signed-off-by: Jose Ricardo Ziviani <jose@ziviani.net>
2016-02-16 13:51:13 -02:00
Solly Ross 0b906a1c3e Merge pull request #219 from noah8713/master
Remove logging in signal handlers
2016-01-11 16:28:02 -05:00
Aliasgar Ginwala 6f0e06772a Remove additional signal calls in websockify that causes novnc to hang.
Openstack nova novnc-proxy services uses websockify to provide support
for nova vms using novnc proxy. At present, novnc hangs every couple of
weeks. It only resumes post restart of the novnc-proxy which is not
good. Hence, this code in websockify is updated to get rid of additional
signal calls to avoid novnc going in hang state even though process is
running. Basically, we are getting rid of existing msg and vmsg calls in
the websocket.py. This is kind of quick fix but we will need an
additional way of figuring out the logging to make it easy to trace in
case of any further failures in future.

closes bug: https://github.com/kanaka/noVNC/issues/556
2016-01-08 17:46:35 -08:00
Samuel 8a13c48428 Merge pull request #215 from miguelxpn/logfile
Add information about new logging files functionality in README
2015-12-05 13:19:44 +01:00
Miguel Xavier Penha Neto b2a93bf709 Add information about new logging files functionality in README
Fix minor typo in mini-webserver section
2015-12-04 22:41:02 -02:00
Solly Ross 9bc002dcf9 Merge pull request #214 from miguelxpn/logfile
Fix log files when daemonizing
2015-12-03 12:51:56 -08:00
Miguel Xavier Penha Neto dc979f042c Fix log files when daemonizing
Save log file descriptor so it's not closed when calling daemonize()
2015-12-02 15:21:21 -02:00
Solly Ross 72b629838a Merge pull request #205 from miguelxpn/logfile
Add support for log files
2015-12-01 10:25:23 -08:00
Miguel Xavier Penha Neto d947fb6e30 Add support for log files
Override log_message in websocket.py so messages from send_error are properly saved into the log files

Closes #204
2015-12-01 15:25:17 -02:00
Solly Ross 8dacbc974c Bump NPM Version
This commit is prep for releasing the Node version for v0.7.1
on NPM.

Closes #199.
2015-10-12 15:37:03 -04:00
Solly c415521214 Merge pull request #201 from quinox/basicauth
Verify username/password with BasicAuth plugin
2015-10-06 22:39:27 -04:00
Ceesjan Luiten 5bd6554651 Verify username/password with BasicAuth plugin 2015-10-06 12:09:22 +02:00
Joel Martin 50cc65f1e4 Merge pull request #198 from halfgaar/master
Clarified SSL section in README
2015-10-05 12:15:50 -05:00
Wiebe Cazemier 3c04cf8c45 Clarified SSL section in README 2015-10-05 11:27:36 +02:00
Solly 62c3a59192 Merge pull request #197 from miguelxpn/issue196
Add support for IPv6 addresses in tokens
2015-09-30 16:53:56 -04:00
Miguel Xavier Penha Neto e401701311 Added support for IPv6 addresses in tokens
Fixes #196
2015-09-30 16:04:19 -03:00
Solly 714aa34e4e Merge pull request #194 from kanaka/feature/http-auth-plugins
Rework Auth Plugins to Support HTTP Auth
2015-08-28 13:52:58 -04:00
Solly Ross 05cac26257 Merge pull request #192 from grz0/master
Fix bug in JSONTokenApi plugin

Closes #192
2015-08-27 18:09:58 -04:00
grz0 487db5f7c9 Fix bug in JSONTokenApi plugin
`Response#json` is a method, not a property, in the
requests library.

[directxman12: removed unnecessary calls to str]
2015-08-27 18:08:39 -04:00
Arata Notsu f693871c58 Avoid UnboundLocalError for exc
Previously exc was set only when an exception occurs in the inner
try (the one contains call to self.poll), so an error in the other
part causes an UnboundLocalError.

Closes #178
2015-08-27 18:03:38 -04:00
Solly b445296816 Merge pull request #185 from timkurvers/fix/js/drop-base64-dependency
Drop pkrumins/node-base64 dependency
2015-08-27 17:58:24 -04:00
Solly Ross 1e2b5c2256 Rework Auth Plugins to Support HTTP Auth
This commit reworks auth plugins slightly to enable
support for HTTP authentication.  By raising an
AuthenticationError, auth plugins can now return
HTTP responses to the upgrade request (such as 401).

Related to kanaka/noVNC#522
2015-08-25 17:52:20 -04:00
Solly Ross 6c1543c05b Fix auth plugins on Python 3.x
Python 3 does not have a `getheader` method on the header object,
and instead uses just `get`.
2015-08-25 17:50:22 -04:00
Solly b7684e0914 Merge pull request #186 from timkurvers/fix/js/node-modules-ignore
Correct .gitignore path for js node_modules
2015-08-11 13:37:57 -04:00
Solly 12432c9b06 Merge pull request #187 from timkurvers/fix/js/spdx-license-identifier
Correct SPDX license identifier for LGPL-3.0
2015-08-05 15:32:56 -04:00
Tim Kurvers 2051c2419f Correct SPDX license identifier for LGPL-3.0 2015-08-01 16:32:56 +02:00
Tim Kurvers cb6b309dad Ignore node_modules correctly 2015-08-01 16:19:30 +02:00
Tim Kurvers addc2e6b20 Drop pkrumins/node-base64 dependency 2015-08-01 16:10:58 +02:00
Solly Ross 69c04c819c Update to 0.7.0
See CHANGES.txt for details.
2015-07-23 21:02:37 -04:00
Till Zimmermann 92fc7872c7 Allow tab to be sent via telnet 2015-07-06 23:54:28 +02:00
Solly 558a6439f1 Merge pull request #176 from crodjer/venv-with-run
Make `run` respect virtualenv configuration
2015-06-02 15:39:03 -04:00
Rohan Jain 2b9e0a5794 Make run respect virtualenv configuration
Signed-off-by: Rohan Jain <crodjer@gmail.com>
2015-05-15 16:54:38 +05:30
Solly 3371090909 Merge pull request #175 from kanaka/bug/catch-interrupted-syscall
Catch interrupted system call
2015-05-13 16:52:31 -04:00
Bennett Kanuka 1f960d9f3c Catch interrupted system call
Closes #166
2015-05-13 16:15:25 -04:00
Solly Ross 1221960baa Introduce strict mode
This commit introduces strict mode, which is on by default.  Currently
strict mode only enforces client-to-server frame masking.  However,
in the future, it might enforce other parts of the RFC as well.

Closes #164
2015-05-13 16:03:57 -04:00
Solly Ross 2e57ee3159 Enable Travis
This commit enables running the unit tests on Travis for Python 2.6,
2.7, 3.3, and 3.4.  Note that Travis does not support Python 2.4, so
we cannot test there.
2015-05-13 16:03:57 -04:00
Solly Ross 04fd789a67 Update Tests and Test Plugins
This commit updates the unit tests to work with the current code
and adds in tests for the auth and token plugin functionality.
2015-05-13 16:03:57 -04:00
Solly Ross d5216c3166 Process plugin parameters in main
Previously, we just passed the values of '--*-plugin' and
'--*-source' directly to `LibProxyServer` and `WebSocketProxy`,
which handled turning that into an instance of the plugin class.
Now, that's done in main, and the classes receive an instance
directly.
2015-05-13 16:03:56 -04:00
Solly Ross 11f9a6cf10 Fix bug in ReadOnlyTokenFile
ReadOnlyTokenFile didn't initialize `self._targets` to `None`,
causing issues.
2015-05-13 16:03:37 -04:00
Solly Ross df10501615 Introduce Auth Plugins
Auth plugins provide a generic interface for authenticating requests.

The plugin name is specified using the '--auth-plugin' option, and
may either be the name of a class from `websockify.auth_plugins`,
or a fully qualified python path to the auth plugin class (see below).

An optional plugin parameter can be specified using the '--auth-source'
option (a value of `None` will be used if no '--auth-source' option is
specified).

Auth plugins should inherit from `websockify.auth_plugins.BasePlugin`,
and should implement the `authenticate(headers, target_host, target_port)`
method.  The value of the '--auth-source' option is available as
`self.source`.

One plugin is currently included: `ExpectOrigin`.  The `ExpectOrigin`
plugin checks that the 'Origin' header is an expected value.  The list
of acceptable origins is passed using the plugin source, as a
space-separated list.
2015-05-13 16:03:37 -04:00
Solly Ross d94b944f93 Restore functionaltiy to file_only.
There was a bug in WebSocketServer that prevented the `file_only`
parameter from actually being set as an instance property, causing
directory listings to appear even with `file_only=True`.  This
commit fixes that.

See-Also: https://bugs.launchpad.net/nova/+bug/1447675
2015-05-13 16:03:37 -04:00
Aric Stewart 52adf957b3 Add ping heartbeat option
With this option we will ping the client with a heartbeat.
Helpful for connection through firewalls that may disable inactive
connections.
2015-04-14 16:09:26 -05:00
Aric Stewart 731fd20796 Add option to turn on auto-pong
This allows the websockify server to respond to heart beat ping
messages sent by clients
2015-04-13 14:57:24 -05:00
Solly Ross 52c2e62535 Fix bug in token_plugin/target_cfg support
Previously, if no `target_cfg` flag was used, the `target_cfg` option
would not get removed from the opts dict, causing an error when it got
passed through to `WebSocketProxy`.  Now we always remove it.

Fixes #168.
2015-04-09 11:43:20 -04:00
Solly ac9d357c87 Merge pull request #161 from rafaelfolco/bug/150-websocket-bigendian
BUGFIX:  Websocket frame corruption on big-endian #150
2015-04-07 12:51:52 -04:00
Solly ce07749223 Merge pull request #162 from kanaka/feature/token-plugins
Introduce Token Plugins
2015-04-07 12:51:02 -04:00
Rafael Folco af10f458a1 BUGFIX: Websocket frame corruption on big-endian #150
This patch fixes noVNC endianess problem on handshake.
It affects noVNC sessions on Big Endian platforms.

Fixes #150
2015-04-07 09:36:21 -03:00
Solly Ross 69a8b928aa Introduce Token Plugins
Token plugins provide a generic interface for transforming a token
into a `(host, port)` tuple.

The plugin name is specified using the '--token-plugin' option,
and may either be the name of a class from `websockify.token_plugins`,
or a fully qualified python path to the token plugin class (see below).

An optional plugin parameter can be specified using the '--token-source'
option (a value of `None` will be used if no '--token-source' option is
passed).

Token plugins should inherit from `websockify.token_plugins.BasePlugin`,
and should implement the `lookup(token)` method.  The value of the
'--token-source' option is available as `self.source`.

Several plugins are included by default.  The `ReadOnlyTokenFile`
and `TokenFile` plugins implement functionality from '--target-config'
(with the former only reading the file(s) once, and the latter reading
them every time).  The 'BaseTokenAPI' plugin fetches the value from
an API, returning the result of `process_result(response_object)`.
By default, `process_result` simply returns the text of the response,
but may be overriden.  The `JSONTokenAPI` does just this, returning
the 'host' and 'port' values from the response JSON object.

The old '--target-config' option is now deprecated, and maps to the
`TokenFile` plugin under the hood.

Also-Authored-By: James Portman (@james-portman)

Closes #157
2015-03-26 16:21:25 -04:00
Solly 19b558e4cd Merge pull request #159 from vaibhavsagar/python3-trove
Add Python 3 trove classifiers.
2015-03-17 10:32:40 -04:00
Vaibhav Sagar dcdf0a0b6c Add Python 3 trove classifiers.
This makes <http://py3readiness.org> display the status of this package correctly :).
2015-03-17 07:20:26 +11:00
Solly 23045cb212 Merge pull request #155 from kanaka/bug/154-no-implicit-relative-imports
Don't use implicit relative imports
2015-02-06 11:29:57 -05:00
Solly Ross acd276e1a2 Don't use implicit relative imports
Implicit relative imports don't work in Python 3.  This converts
implicit relative imports into absolute imports
(e.g. `import websocket` becomes `from websockify import websocket`).

Fixes #154
2015-02-03 16:52:29 -05:00
Solly 999a133bc5 Merge pull request #128 from ags131/patch-1
Added 'websockify.js' to package.json files list
2015-01-05 12:15:56 -05:00
Joel Martin f36877c684 Merge pull request #140 from rpodgorny/python3
python3 compatibility fixes
2014-10-02 10:02:11 -05:00
Radek Podgorny 303a71310c python3 compatibility fixes 2014-10-02 11:42:17 +02:00
samhed 63209f84ca sync with commit from PR #347 in noVNC 2014-08-19 14:13:00 +02:00
Joel Martin d37e729587 Merge pull request #129 from mmb/master
Fix typo in reaping zombies message.
2014-05-20 18:01:00 -05:00
Matthew M. Boedicker 12191d266b Fix typo in reaping zombies message. 2014-05-20 14:43:35 -07:00
ags131 67a12a2394 Fixed Package.json
Added websockify.js to the files section, this fixes #90 and allows NPM to properly install
2014-05-16 11:56:24 -05:00
samhed 6c526fd645 remove some trailing whitespaces 2014-04-14 14:20:00 +02:00
liyiwei 712e17aaef kill 9 warnings when compile on OS X 10.9 2014-04-07 14:40:27 +08:00
liyiwei e36a59d6a1 add run-once option help message 2014-04-07 12:46:50 +08:00
samhed 6c1a2e9032 Avoid using the %-operator, URL-escaped strings can contain extra %'s which can cause bugs. 2014-03-18 15:21:13 +01:00
Solly Ross 739af6ecb4 Update to v0.6.0
*** NOTE ***

This version of websockify will break existing code which sub-classes
`WebsocketProxy` -- see pull requests #110 and #111
2014-02-18 17:03:09 -05:00
Joel Martin 56b740ef5c README: update with general contact info. 2014-02-03 09:26:03 -06:00
Solly Ross 18e70c52e1 Fix default log level in echo and load tests
Since we switched to using the `logging` module to log
in pull request #100, none of the messages on the 'INFO'
level were being shown from `tests/echo.py` and
`tests/load.py`, since the default log level is 'WARNING'.

Now, the log level is set to INFO in `tests/echo.py` and
`tests/load.py`, to match the log level in the main websockify
executable.

Fixes #109
2014-01-30 17:11:20 -05:00
Joel Martin cc3ccf0ddd README: fix wrap mode examples. 2014-01-13 13:25:13 -06:00
chummm f81de71522 fix cygwin compilation 2013-12-27 01:58:32 +00:00
astrand 38db12c2b0 Merge pull request #111 from astrand/master
Refactor to use standard SocketServer RequestHandler design.
2013-12-19 01:31:14 -08:00
Peter Åstrand (astrand) a749611370 Merge remote branch 'upstream/master' 2013-12-19 10:28:37 +01:00
Peter Åstrand (astrand) b662d185ca Prepare for fixing https://github.com/kanaka/websockify/pull/111
Move around functions and methods, so that connection-related and
server-related stuff are close together.

This patch just moves things around - it does not change anything at
all. This can be verified with:

git diff | grep ^- | cut -c 2- | sort > removed
git diff | grep ^+ | cut -c 2- | sort > added
diff -u removed added
2013-12-19 10:24:36 +01:00
Peter Åstrand (astrand) 6de6933819 Minor whitespace and layout tweaks, to reduce diff against
upstream/master.
2013-12-17 14:20:14 +01:00
Peter Åstrand (astrand) f46db48399 Merge remote branch 'upstream/master'
Conflicts:
	websockify/websocket.py
2013-12-17 14:04:30 +01:00
Peter Åstrand (astrand) 8049ddfe26 Cherry-picked 4e3388964a from
astrand/websockify:

    Prepare for fixing https://github.com/kanaka/websockify/issues/71:
    Move around functions and methods, so that connection-related and
    server-related stuff are close together.

    This patch just moves things around - it does not change anything at
    all. This can be verified with:

    git diff websocket.py | grep ^- | cut -c 2- | sort > removed
    git diff websocket.py | grep ^+ | cut -c 2- | sort > added
    diff -u removed added
2013-12-17 13:56:20 +01:00
Peter Åstrand (astrand) f64e3dea51 Merge remote branch 'upstream/master', after #110 was merged. 2013-12-16 16:18:41 +01:00
astrand 17455afe4d Merge pull request #110 from astrand/rename-self-client
Rename self.client and new_client - prepare for #72 / #111
2013-12-16 05:45:03 -08:00
Peter Åstrand (astrand) 047ce47742 Rename new_client to new_websocket_client, in order to have a better
name in the SocketServer/HTTPServer request handler hierarchy. Prepare
for merge pull request #72. This work has been picked out of
7b3dd8a6f5 .
2013-11-28 13:33:28 +01:00
Peter Åstrand (astrand) 558402848e Rename self.client to self.request, in preparation for merging pull
request #72. The standard Python SocketServer/BaseRequestHandler
requires this name.
2013-11-28 13:23:50 +01:00
Peter Åstrand (astrand) db93395061 Follow up on 131f9ea645: Proper logging
in request handler class.
2013-11-28 12:37:57 +01:00
Peter Åstrand (astrand) e246e98b20 Merge commit '34a1b68d79a13c03aa63b5c4194796341c9383fe'
* commit '34a1b68d79a13c03aa63b5c4194796341c9383fe':
  Clarify ssl module build for old python versions.
2013-11-28 09:34:43 +01:00
Peter Åstrand (astrand) 7ecfa4f384 Merge commit 'a04edfe80f54b44df5a3579f71710560c6b7b4fc'
* commit 'a04edfe80f54b44df5a3579f71710560c6b7b4fc':
  Added temp dir for unit test data and cleanup
2013-11-28 09:34:33 +01:00
Peter Åstrand (astrand) bc216fb7d1 Merge commit 'a47be21f9fa69ddf8d888ff9e3c75cdfc9e31c00'
* commit 'a47be21f9fa69ddf8d888ff9e3c75cdfc9e31c00':
  Added unit tests for websocket and websocketproxy
2013-11-28 09:32:49 +01:00
Peter Åstrand (astrand) b92528aeba Merge commit 'c3acdc2e38f871e28ffda1847b4338c4b02296b8'
* commit 'c3acdc2e38f871e28ffda1847b4338c4b02296b8':
  Adds optional TCP_KEEPALIVE to WebSocketServer
2013-11-28 09:32:30 +01:00
Peter Åstrand (astrand) 81e2a53692 Merge commit '13c99bcf053f7f3af8ba84c0d963a9591e020f49'
* commit '13c99bcf053f7f3af8ba84c0d963a9591e020f49':
  Fix search path construction in tests.
2013-11-28 09:14:25 +01:00
Peter Åstrand (astrand) 602248425a Merge commit 'b4e0b534d5d04d57265045b4baf49dd81555064b'
* commit 'b4e0b534d5d04d57265045b4baf49dd81555064b':
  Fix crash when an import is missing
2013-11-28 09:09:03 +01:00
Peter Åstrand (astrand) 3b802c08b7 Merge commit '32b0567343aee7753b2b6be1bc1ee9a69657ba26'
* commit '32b0567343aee7753b2b6be1bc1ee9a69657ba26':
  Fix syntax errors in other/websockify.rb
2013-11-28 09:07:52 +01:00
Peter Åstrand (astrand) 972b30ddc2 Merge commit '0e5c3ecfda3b1506b41412052db75d84df2b4ae7'
* commit '0e5c3ecfda3b1506b41412052db75d84df2b4ae7':
  Handle SIGCHLD properly for multiprocessing
2013-11-28 09:07:41 +01:00
Peter Åstrand (astrand) f58b49fa08 Merge commit 'a61ae52610642ae58e914dda705df8bb9c8213ec'
* commit 'a61ae52610642ae58e914dda705df8bb9c8213ec':
  fixed 1.8 compatibility bug for OpenSSL::SSL::SSLSocket#read_nonblock vs #readpartial tested in 1.8 and 2.0
  adding SSL support and Ruby1.9 support
2013-11-28 09:07:30 +01:00
Peter Åstrand (astrand) 131f9ea645 Merge commit '477dce6cf86d61b20a394f3cbf3170e60d199658'
* commit '477dce6cf86d61b20a394f3cbf3170e60d199658':
  websocket: use python logging module
  websocket: fix exception statement introduced by comment 903e3f06ee557

Adapted to new standard SocketServer RequestHandler design. For
example, this means that self.i_am_client is not needed.
2013-11-28 09:05:24 +01:00
Peter Åstrand (astrand) cbf05f84fe Merge commit '4459824cc8196ad78fe9258b6c560ad46fe4cd52'
* commit '4459824cc8196ad78fe9258b6c560ad46fe4cd52':
  websocket: do not exit at the middle of process
  websocket: restore signals after processing
  websocket: support SIGTERM as exit signal
2013-11-27 14:49:54 +01:00
Peter Åstrand (astrand) 611da86353 Merge commit 'a7fa97f0e14926cc4433483fcb7581e0b3782140'
* commit 'a7fa97f0e14926cc4433483fcb7581e0b3782140':
  WebSocketProxy: support non path target_cfg
2013-11-27 13:41:00 +01:00
Peter Åstrand (astrand) fb4ac5ae51 Merge commit 'edde5cd0ff6059bddae10c9b9faf0b3e8f388a9e'
* commit 'edde5cd0ff6059bddae10c9b9faf0b3e8f388a9e':
  Fixed wiki reference
2013-11-27 13:38:03 +01:00
Peter Åstrand (astrand) 063c7de783 Merge commit 'bff3c373b32ebf707085e3c677bfad19b44fa054' 2013-11-27 13:34:17 +01:00
Peter Åstrand (astrand) 08d37e0deb Merge commit 'f30ad05c70ab2a43c9078e2f79da40f1dc0c60ec'
* commit 'f30ad05c70ab2a43c9078e2f79da40f1dc0c60ec':
  Fix #97: rebind.so not found when installed
2013-11-27 13:33:30 +01:00
Peter Åstrand (astrand) ff30e5461f Merge commit 'ab389d4e7114d7ddbfd085591d336ea5cc06c00d'
* commit 'ab389d4e7114d7ddbfd085591d336ea5cc06c00d':
  Collect zombie child processes within server loop
2013-11-27 13:30:30 +01:00
Peter Åstrand (astrand) 4071291fa9 Merge commit '264f8fdd7f12bd5b9f6813fb8de81c55b6328d9b'
* commit '264f8fdd7f12bd5b9f6813fb8de81c55b6328d9b':
  Update to version 0.5.1
2013-11-27 13:30:22 +01:00
Peter Åstrand (astrand) 611effd83b Merge commit '36cb8f4676c7b5ff34bd22ad729e00e77efb6f00'
* commit '36cb8f4676c7b5ff34bd22ad729e00e77efb6f00':
  Move javascript websockify files to other/js
2013-11-27 13:30:13 +01:00
Peter Åstrand (astrand) b63d197292 Merge commit '36fcd5784fa0825eedbf31d91bc42c970605ddb4'
* commit '36fcd5784fa0825eedbf31d91bc42c970605ddb4':
  Add package file for websockify.js
2013-11-27 13:30:05 +01:00
Peter Åstrand (astrand) cf901ddac5 Merge commit '46450577c2fb119fc5bf0ac09664f22651a080d0' 2013-11-27 13:29:54 +01:00
Peter Åstrand (astrand) 122985bd67 Merge commit 'd3ba23fa64d79eeb602ff1015ec31014fd8e9b35'
* commit 'd3ba23fa64d79eeb602ff1015ec31014fd8e9b35':
  Update to c0855c6cae of web-socket-js
2013-11-27 13:29:45 +01:00
Peter Åstrand (astrand) 19c8482236 Merge commit '6d27b5d321978586ea1601f757ead73dfba03da7'
* commit '6d27b5d321978586ea1601f757ead73dfba03da7':
  Add 2 arguments to websockify.WSRequestHandler

As of now, only implemented the first command; see #83 for details.
2013-11-27 13:27:38 +01:00
Peter Åstrand (astrand) 33a1bd2337 Merge commit 'b7f255ce0b21dc42189205b1f0e46b4f1d9854f9'
* commit 'b7f255ce0b21dc42189205b1f0e46b4f1d9854f9':
  Clarify messages when optional modules are not found.
2013-11-27 12:27:43 +01:00
Peter Åstrand (astrand) 5f8cb96bab Merge commit '477947ba96a00032ae35ac55fd02a4a5f485497e'
* commit '477947ba96a00032ae35ac55fd02a4a5f485497e':
  Remove wsproxy references. Sync launch.sh from noVNC.
2013-11-27 12:27:31 +01:00
Peter Åstrand (astrand) 6ddfaa86ae Merge commit '33e9a21ce4e38d52f43fe775fb154fc71c09c827'
* commit '33e9a21ce4e38d52f43fe775fb154fc71c09c827':
  Add gimite/web-socket-js submodule for DFSG compliance.
2013-11-27 12:26:53 +01:00
Peter Åstrand (astrand) 4dc7c0da7a Merge commit '2d078e8cd83735dad7d98fadcece652d93e2a037'
* commit '2d078e8cd83735dad7d98fadcece652d93e2a037':
  correctly include include directory in egg.
2013-11-27 11:36:47 +01:00
Joel Martin 34a1b68d79 Clarify ssl module build for old python versions. 2013-11-20 07:30:23 -06:00
Joel Martin a04edfe80f Merge pull request #105 from dosaboy/topic/unit-test-cleanup
Added temp dir for unit test data and cleanup
2013-11-20 05:21:18 -08:00
Edward Hope-Morley 32c1abd5d9 Added temp dir for unit test data and cleanup
Unit test data will now go to a temporary dir that will be deleted
once the test completes. The unit tests also setup a logger which
will persist so that it can be inspected once tests complete.

Also fixes a bug where instance var is missing from decode_hybi()

Co-authored-by: natsume.takashi@lab.ntt.co.jp
2013-11-14 12:38:03 +00:00
Joel Martin a47be21f9f Merge pull request #94 from dosaboy/topic/add-unit-tests
Added unit tests for websocket and websocketproxy
2013-10-29 09:44:48 -07:00
Edward Hope-Morley 5e0ff7d855 Added unit tests for websocket and websocketproxy
To run the unit tests just run tox from the top
level directory which will try to run unit tests
for most versions of python. Requires tox to be
installed. To run tox for a specifice env, run
tox -e<env> e.g. for python 2.7 run 'tox -epy27'.

Co-authored-by: natsume.takashi@lab.ntt.co.jp
2013-10-29 16:19:39 +00:00
Joel Martin c3acdc2e38 Merge pull request #93 from dosaboy/topic/set-keepalive-options
Adds optional TCP_KEEPALIVE to WebSocketServer
2013-10-29 08:18:53 -07:00
Joel Martin 13c99bcf05 Fix search path construction in tests.
This way the tests can be run directly from within the tests directory
and they might also have a chance of running on Windows (where the
path separator is different).
2013-10-29 09:41:26 -05:00
Samuel b4e0b534d5 Merge pull request #104 from stevschmid/patch-1
Fix crash when module is missing
2013-10-24 04:22:44 -07:00
Steven Schmid be4119f84f Fix crash when an import is missing
self.msg is not available when checking the imports.

I had the problem on a host where numpy is missing (python 2.7.3).
2013-10-24 11:42:49 +02:00
Solly 32b0567343 Merge pull request #103 from dellsystem/master
Fix syntax errors in other/websockify.rb
2013-10-21 18:29:45 -07:00
dellsystem 82fe329129 Fix syntax errors in other/websockify.rb 2013-10-21 20:59:16 -04:00
Solly 0e5c3ecfda Merge pull request #102 from DirectXMan12/master
Handle SIGCHLD properly for multiprocessing (fixes #101)
2013-10-21 17:16:09 -07:00
Solly Ross 53f1f1989e Handle SIGCHLD properly for multiprocessing
This commit should fix #101 by enabling a special SIGCHLD
handler for when multiprocessing is in use.  The handler
simply calls `multiprocessing.active_children()` (which in
turn calls `_cleanup()`) upon receiving a SIGCHLD.  Now,
the `fallback_SIGCHLD` is only called when `multiprocessing`
is not in use.  See also #95.
2013-10-21 16:52:42 -04:00
Edward Hope-Morley 081046b6cd Adds optional TCP_KEEPALIVE to WebSocketServer
TCP_KEEPALIVE is now enabled by default. Settings for
KEEPCNT, KEEPINTVL and KEEPIDLE can be supplied when
creating WebSocketServer and KEEPALIVE can also be
disabled if required.

Also adds new unit test for testing.

Co-authored-by: natsume.takashi@lab.ntt.co.jp
2013-10-16 11:24:21 +01:00
Joel Martin a61ae52610 Merge pull request #86 from chrislee35/master
OpenSSL Support for Ruby Module of Websockify
2013-10-15 10:32:57 -07:00
Joel Martin 477dce6cf8 Merge pull request #100 from alonbl/log
websocket: use python logging module
2013-10-15 09:41:35 -07:00
Alon Bar-Lev 8a0a47223d websocket: use python logging module
WebSocketServer is a library module, as such, it cannot assume it can
write output to process stdout.

Python logging module is designed in order to allow subscribers to
handle the output out of modules. It is simple and generic mechanism to
separate between data producer and data handling.

Python logging API also has the nature of log level, so the verbose
parameter can probably be obsoleted in favor of logging level. And of
course the logging API has built in support for exception tracebacks, no
need for manual format.

Per upstream request a wrapper is created around python logging to
enable shorter statements and optional replacement.

Add --traffic parameter for traffic specific debug, this is required as
it uses direct unformatted stdout output.

Signed-off-by: Alon Bar-Lev <alon.barlev@gmail.com>
2013-10-15 19:18:17 +03:00
Alon Bar-Lev 1f798214de websocket: fix exception statement introduced by comment 903e3f06ee557
Signed-off-by: Alon Bar-Lev <alon.barlev@gmail.com>
2013-10-15 19:18:17 +03:00
Joel Martin 4459824cc8 Merge pull request #98 from alonbl/apicleanup
Minor API cleanups
2013-10-14 13:12:40 -07:00
Alon Bar-Lev c2a40d6900 websocket: do not exit at the middle of process
WebSocketServer is a library module, as such it should not exit process
but return from a method, allowing the caller to execute process show
down.

Signed-off-by: Alon Bar-Lev <alon.barlev@gmail.com>
2013-10-14 22:17:19 +03:00
Joel Martin a7fa97f0e1 Merge pull request #99 from alonbl/targetconfig
WebSocketProxy: support non path target_cfg
2013-10-14 11:38:05 -07:00
Alon Bar-Lev 1190fe1204 websocket: restore signals after processing
WebSocketServer is a library module, as such it should try to restore state
after processing, to allow caller to resume normal operation.

Signed-off-by: Alon Bar-Lev <alon.barlev@gmail.com>
2013-10-14 21:13:11 +03:00
Alon Bar-Lev 7026e26d68 websocket: support SIGTERM as exit signal
Similar to SIGINT that is already supported, support SIGTERM in daemon
and non daemon modes.

Signed-off-by: Alon Bar-Lev <alon.barlev@gmail.com>
2013-10-14 21:01:44 +03:00
Alon Bar-Lev 37e40a78f2 WebSocketProxy: support non path target_cfg
The WebSocketProxy class is usable for creating derived applications
with different logic, especially for the target validation.

Current code assumes that target is a path while in other implementation
it can be object that is loaded at initialization.

This change moves the conversion to absolute path into main function, so
that the WebSocketProxy class will not make that assumption.

Signed-off-by: Alon Bar-Lev <alon.barlev@gmail.com>
2013-10-14 20:31:24 +03:00
Samuel edde5cd0ff Merge pull request #91 from MartinF/master
Fixed wiki reference
2013-10-09 06:50:08 -07:00
Joel Martin bff3c373b3 Merge pull request #96 from DirectXMan12/master
Enable Process Reaping in All Conditions
2013-09-27 06:05:55 -07:00
Joel Martin f30ad05c70 Fix #97: rebind.so not found when installed
This should fix the upstream Debian bug:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=719889
2013-09-27 07:42:57 -05:00
directxman12 354dd6b0a2 Enable Process Reaping in All Conditions
Process reaping via the SIGCHLD handler is now enabled in all
circumstances, instead of just when os.fork is being used.

Fixes #95
2013-09-20 14:12:35 -04:00
Martin From e06de83295 Fixed wiki reference 2013-09-09 11:32:57 +02:00
Joel Martin ab389d4e71 Merge pull request #85 from dillaman/master
Collect zombie child processes within server loop
2013-07-02 10:55:53 -07:00
chrislee35 eee946d2cf fixed 1.8 compatibility bug for OpenSSL::SSL::SSLSocket#read_nonblock vs #readpartial
tested in 1.8 and 2.0
2013-07-02 22:16:01 +09:00
chrislee35 73af324a3a adding SSL support and Ruby1.9 support 2013-07-02 21:38:22 +09:00
Jason Dillaman 832118e61a Collect zombie child processes within server loop 2013-06-28 15:22:35 -04:00
Joel Martin 264f8fdd7f Update to version 0.5.1
*** NOTE ***

This version of websockify no longer supports the old Hixie protocol.
2013-06-27 16:35:54 -05:00
Joel Martin 36cb8f4676 Move javascript websockify files to other/js 2013-06-27 16:29:17 -05:00
Joel Martin 36fcd5784f Add package file for websockify.js 2013-06-27 16:29:17 -05:00
Joel Martin 46450577c2 Use upstream einaros/ws 0.4.27 with sub-protocol support.
Also, some connection error handling.
2013-06-27 16:29:17 -05:00
Joel Martin d3ba23fa64 Update to c0855c6cae of web-socket-js
Update both the submodule and the swf build. The submodule now
contains the unobfuscated source for swfobject.js which should make
websockify more DFSG compliant.
2013-06-27 16:29:17 -05:00
Joel Martin 6d27b5d321 Merge pull request #84 from nttdatainc-openstackers/master
Fix for issue #83
2013-06-27 14:01:07 -07:00
NTT Data OpenStackers 888e75a8fb Add 2 arguments to websockify.WSRequestHandler
This patch adds 2 arguments to websockify.WSRequestHandler for security:

* file_only: returns 404 response if non-file contents are requested.
             Required to disable directory listing.

* no_parent: returns 403 response if contents out of the web root are
             requested. Required to disable directory traversal.
2013-06-24 06:09:01 -07:00
Joel Martin b7f255ce0b Clarify messages when optional modules are not found. 2013-04-19 17:14:20 -05:00
Joel Martin 477947ba96 Remove wsproxy references. Sync launch.sh from noVNC. 2013-04-15 12:22:08 -05:00
Joel Martin 33e9a21ce4 Add gimite/web-socket-js submodule for DFSG compliance. 2013-04-12 08:24:07 -05:00
Joel Martin 2d078e8cd8 Merge pull request #76 from SlapOS/include
correctly include include directory in egg.
2013-04-03 09:44:37 -07:00
Cédric de Saint Martin d6d960dbe5 correctly include include directory in egg. 2013-04-03 12:12:37 +02:00
Peter Åstrand (astrand) ed109d7ec8 Fix Python3 compatibility when using --libserver. 2013-03-20 15:09:58 +01:00
Peter Åstrand (astrand) bc917863e0 Improved class documentation. 2013-03-20 13:30:16 +01:00
Peter Åstrand (astrand) e964c1edff Let our ProxyRequestHandler be default. This allows you to inherit
from WebSocketProxy without having to specify handler class.
2013-03-20 11:34:46 +01:00
Peter Åstrand (astrand) f5e42ff6f4 Move WebSocketProxy class so that it is defined after the
requesthandler. Removed comments about above/below which does not make
sense any longer. No functional changes.
2013-03-20 11:30:38 +01:00
Peter Åstrand (astrand) f594d70daf Removed unused import of SimpleHTTPRequestHandler. 2013-03-20 11:00:34 +01:00
Peter Åstrand (astrand) d0608a63b6 Make echo.py and load.py work again, after the refactoring of
websocket.py:

* With echo.py, which doesn't need any server configuration, we can
  just switch over our application class to inherit from
  WebSocketRequestHandler instead of WebSocketServer. Also, need to
  use the new method name new_websocket_client.

* With load.py, since we have the "delay" configuration, we need both
  a server class and a request handler.

Note that for both tests, I've removed the raising of
self.EClose(closed). This is incorrect. First of all, it's described
as "An exception before the WebSocket connection was established", so
not suitable for our case. Second, it will cause send_close to be
called twice. Finally, self.EClose is now in the WebSocketServer
class, and not a member of the request handler.
2013-03-20 10:03:04 +01:00
Peter Åstrand (astrand) 09f3ec7125 Rename self.client to self.request, ie adapt to:
>commit b9e1295f7a
>    Prepare for solving https://github.com/kanaka/websockify/issues/71:
>
>    Rename self.client to self.request, since this is what standard
>    SocketServer request handlers are using.
2013-03-20 09:03:18 +01:00
Peter Åstrand (astrand) 95593ac4bf Merge branch 'master' of github.com:astrand/websockify 2013-03-18 14:59:03 +01:00
Peter Åstrand (astrand) 1eecc7b17a Merge remote branch 'upstream/master' 2013-03-18 14:50:46 +01:00
Peter Åstrand (astrand) b05b773bd7 Corrected last commit. 2013-03-18 13:25:53 +01:00
Peter Åstrand (astrand) debc926612 Renamed CustomProxyServer to WebSocketProxy; this was the earlier name.
Also, call the server instance "server", not "httpd", even when using
LibProxyServer.
2013-03-18 13:22:48 +01:00
Peter Åstrand (astrand) 70eb75a3e6 Fix error with modern Python 2.X versions:
TypeError: exceptions must be old-style classes or derived from
BaseException, not str

Thus, we are not allowed to raise a string. Raise Exception instead.
2013-03-18 12:04:50 +01:00
Joel Martin 903198a724 tests: use new module path and remove Hixie code. 2013-03-14 12:24:58 -05:00
Peter Åstrand (astrand) 7b3dd8a6f5 Try to solve https://github.com/kanaka/websockify/issues/71 by
refactoring. Basically, we are dividing WebSocketServer into two
classes: One request handler following the SocketServer Requesthandler
API, and one optional server engine. The standard Python SocketServer
engine can also be used.

websocketproxy.py has been updated to match the API change. I've also
added a new option --libserver in order to use the Python built in
server instead.

I've done a lot of testing with the new code. This includes: verbose,
daemon, run-once, timeout, idle-timeout, ssl, web, libserver. I've
tested both Python 2 and 3. I've also tested websocket.py in another
external service.

Code details follows:

* The new request handler class is called WebSocketRequestHandler,
  inheriting SimpleHTTPRequestHandler.

* The service engine is called WebSocketServer, just like before.

* do_websocket_handshake: Using send_header() etc, instead of manually
  sending HTTP response.

* A new method called handle_websocket() upgrades the connection to
  WebSocket, if requested. Otherwise, it returns False. A typical
  application use is:

    def do_GET(self):
        if not self.handle_websocket():
	   # handle normal requests

* new_client has been renamed to new_websocket_client, in order to
  have a better name in the SocketServer/HTTPServer request handler
  hierarchy.

* Note that in the request handler, configuration variables must be
  provided by the "server" object, ie self.server.target_host.
2013-03-14 16:07:40 +01:00
Peter Åstrand (astrand) 208f83b9a2 Prepare for fixing https://github.com/kanaka/websockify/issues/71:
* Move traffic_legend.

* Since websocket.WebSocketServer.socket is static, don't call it with
  self.socket.
2013-03-14 16:00:11 +01:00
Peter Åstrand (astrand) 4e3388964a Prepare for fixing https://github.com/kanaka/websockify/issues/71:
Move around functions and methods, so that connection-related and
server-related stuff are close together.

This patch just moves things around - it does not change anything at
all. This can be verified with:

git diff websocket.py | grep ^- | cut -c 2- | sort > removed
git diff websocket.py | grep ^+ | cut -c 2- | sort > added
diff -u removed added
2013-03-14 15:50:49 +01:00
Peter Åstrand (astrand) b9e1295f7a Prepare for solving https://github.com/kanaka/websockify/issues/71:
Rename self.client to self.request, since this is what standard
SocketServer request handlers are using.
2013-03-14 15:23:44 +01:00
Joel Martin d3865688c8 README: no longer supporting Hixie.
NOTE: Hixie support is in version 0.4.X. If necessary, I will branch
and apply critical fixes release a new 0.4.X tagged version.
2013-03-12 13:54:11 -05:00
Joel Martin 5a726c2e4d Merge pull request #70 from astrand/master
Remove support for old Hixie protocols
2013-03-12 11:52:30 -07:00
Joel Martin db6a7e3e28 Update to version 0.4.1
*** IMPORTANT NOTE ***

0.4.X is the last minor version to support the Hixie protocol. 0.5.0
will drop the Hixie protocol support. The latest released version of
all major browsers (and web-socket-js) support the IETF 6455 protocol.

- Other changes: add 'include/' sub-dir to source distribution and to
  installed packaged.
2013-03-12 13:46:45 -05:00
Joel Martin d9aedfe7d3 Update to version 0.4.0
*** IMPORTANT NOTE ***

This is the last minor version to support the Hixie protocol. I may do
bug fixes (e.g. 0.4.1) but 0.5.0 will drop the Hixie protocol support.
The latest released version of all major browsers (and web-socket-js)
support the IETF 6455 protocol.

- Other changes: updating TODO and release process notes.
2013-03-12 13:10:53 -05:00
Peter Åstrand (astrand) b2fe57c950 Remove support for old Hixie protocols.
Hybi protocols 7 and 8 are still supported, in addition to
protocol 13 -  RFC 6455.
2013-03-04 09:38:29 +01:00
Joel Martin 805026360e Use Buffer base64 support instead of pkrumins/node-base64 2013-02-19 13:12:10 -06:00
Joel Martin 3d37d21b5f Update to version 0.3.0 and upload to pypi.
Update to 0.3.0 and document uploading to pypi.python.org.

Install thus:
    sudo pip install websockify
2013-01-15 11:49:08 -06:00
Joel Martin c33f0b52e7 In Opera 12.10, set binaryType earlier.
Otherwise, the first message received may be blob depending on timing.
2012-11-14 12:24:08 -05:00
Joel Martin 1d795c0643 Pull include/util.js from noVNC.
Pull version 51562999c7 load_scripts fixes.
2012-11-01 11:07:26 -05:00
Joel Martin c00c0eed1a websocket.py: close lsock on stop.
If WebSocketServer is used as a library with run_once or timeout, then
cleanup the socket listener socket so that when start_server returns
(due to run_once or timeout) then port is freed up.
2012-10-31 12:04:16 -05:00
Joel Martin 47fb367486 websocketproxy.py: fix for python2.4
Thanks to https://github.com/WhiteRavenTechnology for catching this.
2012-10-30 08:34:47 -05:00
Joel Martin 5e16b38524 websocketproxy.py: put client socket handling first.
Should at least mostly address this issue:
https://github.com/kanaka/websockify/issues/63

The problem is that the target in the test case often immediately
closed the target after sending the data. In this case the last data
received from the target is never sent to the client because the
client is not in the list of sockets being selected against (because
it is only added if their is pending data). By moving the client
conditionals first, we give the client socket a chance to be sent data
before the target is detected as close and we terminate the loop.
2012-10-29 18:12:54 -05:00
Joel Martin c728f43c63 README.md: clarify binary vs base64 negotiation. 2012-10-29 17:17:56 -05:00
Joel Martin d1458d0063 websocketproxy.py: better missing token exception. 2012-10-29 17:05:23 -05:00
Joel Martin 66d772a6bc Ignore other/node_modules directory (node.js modules). 2012-10-29 17:04:39 -05:00
Joel Martin a670af376e websockify.js: add encrypted HTTPS/WSS support.
This works a bit differently than python websockify implementation
since the server either runs in HTTP or in HTTPS and both web and
websocket servers only support the same mode. Specifying the --cert
parameter activates encrypted HTTPS/WSS mode.
2012-10-29 16:59:46 -05:00
Joel Martin 16691395e0 websock.js: use iteration to receive binary data
Instead of using apply with the Uint8Array to push the data onto the
receive queue, iterate through the binary data and push it an element
at a time. Apparently, doing an apply with a very large binary array
can blow the stack. Performance-wise this seems equivalent in Chrome
22 and Firefox 16.
2012-10-26 18:01:35 -05:00
Joel Martin 3018cf8c1a websockify.js: executable, fix usage statement. 2012-10-26 18:01:05 -05:00
Joel Martin 6a126405bd websockify.js: binary data, better logs and err handling.
This version requires a patched version of einaros/ws that can be
found here: https://github.com/kanaka/ws You can use the patched
version like this:

    cd websockify/other
    git clone https://github.com/kanaka/ws
    npm link ./ws

Once the upstream 'ws' module supports subprotocol negotiation then
this will no longer be necessary.

Changes:
- Adds support for binary data and subprotocol negotiation of 'base64'
  vs 'binary' with 'binary' preferred if the client offers it.
- Add client address to log messages.
- Close the target when the client closes.
- Catch errors when we try and send to a client that is no longer
  connected.
2012-10-26 16:08:47 -05:00
Joel Martin ee2f269c06 websocket.py: fix recording and refactor unmask.
Fix recording so that it records the actual payload bytes sent to the
client.  This means that if the client and server and using base64
encoding then the captured data will still be base64 encoded. However,
data received from the client is unmasked when recorded. Note that
this is not done efficiently; when recording, client data is unmasked
twice (once for sending on to the target and once for recording). This
could be made more efficient but that would require a refactor of how
frame reception and unmasking works and recording is not considered
a performance sensitive mode.
2012-10-17 11:59:03 -05:00
Joel Martin 780cb8a9e6 util.js, websock.js: sync with noVNC - dynamic script loading.
Sync with noVNC ad29479ca90f9. Use new dynamic script loading
mechanism in util.js.

window.onscriptsload is called when dynamic scripts have loaded
(window.onload fires too early in IE 9).
2012-10-17 11:59:03 -05:00
Joel Martin 388d9573fd Merge pull request #65 from lovelysystems/master
updated version in setup.py
2012-10-15 14:04:27 -07:00
Joel Martin 578dba1987 include/*util.js: update to versions from noVNC. 2012-10-15 16:02:38 -05:00
Joel Martin 124c9a7d88 Change include/websock.js (and deps) to MPL 2.0 license.
The MPL 2.0 license is a "file-level" copyleft license vs the
"project-level" nature of the L/GPL. The intention of the websock.js
file has always been that it should be easy to incorporate into
existing projects and sites whether free/open or
proprietary/commercial. The MPL 2.0 is designed for this sort of
combination project but still requires that any distributed
modifications to noVNC source files must also be published under the
same license.

In addition, the MPL 2.0 allows the code to be used in L/GPL projects
(the secondary license clause). This means that any projects that are
already incorporating noVNC should not be impacted by this change and
in fact it should clarify the licensing situation (the exact
application of the L/GPL to web applications and interpreted code is
somewhat ambiguous).

The dependencies on include/websock.js are also updated to MPL 2.0
including util.js and webutil.js. The base64.js has been updated to
the MPL 2.0 licensed version from Mozilla.

The websockify python code (and other implementations) remain under
a LGPLv3 license.
2012-10-15 16:02:38 -05:00
Jodok Batlogg e53fa10397 updated version 2012-10-15 22:06:50 +02:00
Joel Martin 1295668abb Merge pull request #64 from vishvananda/fix-import
In websockify/__init__.py import everything from websocketproxy and websocket
2012-09-26 07:35:05 -07:00
Vishvananda Ishaya 880257a431 Import everything in websocketproxy and websocket
Old users of the websockify library used websockify.WebSocketProxy
The refactor into a module unneccessarily broke this import. The
current imports in __init__.py don't actually do anything so this
patch changes the import to import everything so that the old import
still works. This appears to be the original intention of the existing
import statements.
2012-09-25 22:24:10 -07:00
Joel Martin 8b3125bcf3 other/websockify.js: arg cleanup, remove deprecated call.
Change deprecated path.exists call to fs.exists.

Confirmed that this runs with node v0.8.9
2012-09-21 08:19:40 -05:00
Joel Martin 471b504799 Merge branch 'master' of github.com:kanaka/websockify 2012-09-21 07:32:54 -05:00
Joel Martin b713acbeff Merge pull request #59 from dosht/master
--unix-target option breaks argument sanity check
2012-09-21 05:31:47 -07:00
Joel Martin ff736e9ad3 Fix issue #60: not all arguments converted
https://github.com/kanaka/websockify/issues/60

String formatting issue with wrapped cmds.
2012-09-21 07:28:08 -05:00
Joel Martin 384c2772fb Merge pull request #61 from vishvananda/fix-popen
Reset SIGPIPE handler when calling Popen

References:

http://www.chiark.greenend.org.uk/ucgi/~cjwatson/blosxom/2009-07-02-python-sigpipe.html

http://bugs.python.org/issue1615376

http://bugs.python.org/issue1652
2012-09-21 05:24:50 -07:00
Joel Martin e6d8d8f242 Gracefully handle errors when popping kwargs.
https://github.com/kanaka/websockify/pull/53
2012-09-21 07:10:34 -05:00
Vishvananda Ishaya ca8efbf657 Reset SIGPIPE handler when calling Popen
Python ignores SIGPIPE on startup, because it prefers to check every
write and raise an IOError exception rather than taking the signal. Most
Unix subprocesses don't expect to work this way. This patch (adapted
from Colin Watson's post at http://tinyurl.com/2a7mzh5) sets SIGPIPE
back to the default action.
2012-09-20 07:46:04 -07:00
mostafa sameh eb6d4e183b Fix --unix-target option 2012-09-18 09:20:39 +02:00
Joel Martin 6d9deda9c5 Pull upstream web-socket-js with IETF 6455 support.
Pull in web-socket-js 7677e7a954.

The biggest change of note is that this updates web-socket-js to IETF
6455 rather than the previous Hixie protocol.
2012-09-17 16:50:46 -05:00
Joel Martin 96890fab97 include/websock.js: cleanup and fix protocol list check.
If a protocol list is specified and we don't support binary WebSockets
then strip binary from the list and check the list to make sure there
is still an option left.
2012-09-17 16:49:36 -05:00
Joel Martin c0d23e27e4 Refactor into python modules: websocket, websocketproxy
Make websockify subdirectory and move websocket.py ->
websockify/websocket.py and websockify ->
websockify/websocketproxy.py. Create a ./run script that launches
websockify as before (unfortunately can't have a websockify script at
the same level since this is now a directory). Make websockify.py
a symlink to ./run. Once the package is installed, the main launch
script will be /usr/bin/websockify.

This makes it easier to package up websockify as a python module.
setup.py should now properly install websockify as a module.

Note that to include the base websocket module/class you will now do:

    import websockify.websocket
    #OR
    from websockify.websocket import WebSocketServer

To import the full websocket proxy functionality:

    import websockify.websocketproxy
    #OR
    from websockify.websocket import WebSocketProxy

This will also help with startup speed slightly because the code in
websocketproxy will now be byte compiled since it is no longer in the
main invocation script.
2012-09-17 14:06:51 -05:00
Joel Martin 2d2798954e websockify version 0.2.0 2012-09-17 12:56:34 -05:00
Joel Martin 44e5fa0b82 Merge pull request #56 from AricStewart/master
Implement --idle-timeout for issue #55
2012-09-06 20:02:04 -07:00
Aric Stewart 82cb31f3b6 change --idle-timeout to reset the idle timeout when active 2012-08-31 10:55:24 -05:00
Aric Stewart 9348dd5208 Implement option --idle-timeout
server exits after TIMEOUT seconds if there are no active connections
2012-08-31 09:24:09 -05:00
Joel Martin 17175afd73 websock.js: make protocols parameter of open().
If no protocols are selected then defaults to ['binary', 'base64'] (or
just 'base64' if there is not full binary type support.

Checks to make sure binary types are fully supported and throws an
exception if they are requested but not supported.
2012-08-16 13:28:28 -05:00
Joel Martin 53b074e8e7 websock.js: simplify rQshiftStr with apply(). 2012-08-16 13:27:50 -05:00
Joel Martin 068065e465 Simpler (but working) binary support.
Instead of trying to handle the receive queue as a typed array, just
replace the base64 encode/decode with conversion from/to typed arrays
and handle the receive and send queue as before (plain Javascript
arrays).

There is a lot of opportunity here for optimization of course, but for
now it's more important that it work properly.
2012-08-16 12:21:21 -05:00
Joel Martin 376872d993 Use WebSocket binary data (no base64 enc/dec) if available.
If typed arrays (arraybuffers) are available and the WebSocket
implementation supports them, then send and receive direct binary
frames and skip base64 encode/decode. Otherwise we just fallback to
the current method of sending base64 encoded strings (with a couple of
extra checks for mode in the send/receive path).

The check for binaryType support in WebSocket is a collosal hack right
now due to the fact that the 'binaryType' property doesn't exist on
the WebSocket prototype. So we have to create a connection to
a localhost port in order to test.

A potentionally big performance boost could probably be achieved by
re-using a larger typed array for storing the data instead of creating
a typed array every time we receive a message.
2012-08-14 15:19:38 -05:00
Joel Martin f55362ff07 websock.js: jslint comments, debug comments, copyright date 2012-08-14 15:18:14 -05:00
Joel Martin 36bdb09630 More verbosity about who closed the connection. 2012-08-14 15:14:00 -05:00
Joel Martin d575e571fd Fix split out handshake parsing for Hixie.
Need the scheme to be accessible when constructing the response for
Hixie clients.
2012-08-14 15:12:48 -05:00
Joel Martin 00e9d3bf29 websockify.rb: correct comment, no SSL support yet. 2012-07-24 09:31:26 -05:00
Joel Martin 26e8095244 websockify: rename config opt, fix config dir reading 2012-07-13 13:17:56 -05:00
Joel Martin e4b9d510f1 websocket.py: split out handshake parsing.
This makes it easier to use the websocket code in a WSGI script in the
future.
2012-07-13 13:09:32 -05:00
Joel Martin 65e96176cb websockify: change cfg file syntax and clean up parsing.
Config file syntax is now like this:

----------------------
    # Comments and blank lines are allow
    token1: host1:port1

    token2: host2:port2
----------------------
2012-07-12 19:34:27 -05:00
Joel Martin 52beba8695 Move target-list processing to websockify.
websocket.py has no concept of target/proxy so any target processing
should happen in websockify itself.

Also:

- remove URL parsing imports from websocket.py since they are not
  needed with SimpleHTTPRequestHandler doing the parsing.

- read the absolute path of the target_list file on startup since the
  --web option will change directories if set.
2012-07-12 19:10:12 -05:00
Hector Sanjuan e17e1158d8 Enable multiple targets in websockify by passing a target-list configuration file.
The --target-list option is used to pass a configuration file on websockify start.

This file contains entries in the form host:port:token, one per line.

When a new connection is open (from noVNC for example), the url should look like:

ws://websockify_host:websockify_port/?token=ABCD

The token is then extracted and checked against the entries in the configuration file.

When the token matches, the connection is proxied to the host:port indicated in the file.

If the configuration file is a folder, then all the entries from files in it are read.
2012-07-11 16:00:13 +02:00
Joel Martin 2a8df6327e Merge pull request #49 from libricoleur/master
Better support of IPv6
2012-06-26 07:40:38 -07:00
Alexandre Sicard 67d4c17516 Allow preference of IPv6 for source_addr
Add the option "-6, --prefer-ipv6". When set, the 'prefer_ipv6' flag in
websocket.py is used so that 'source_addr' is resolved to IPv6 if
available. If 'source_addr' is not set, binds to [::].
2012-06-26 13:57:50 +02:00
Alexandre Sicard 1f5b492e10 Support IPv6 brackets notation
Parse square brackets-enclosed IPv6 for 'source_addr' and 'target_addr'
parameters.
2012-06-26 13:55:19 +02:00
Joel Martin cb925eb486 doc/websockify.1: add man page for websockify command.
Mostly it is based on the project README.md but with some tweaks and
extra content removed.

Thanks for Adam Young <ayoung@redhat.com> for the original version of
this.

Also a decent man format reference is here:
http://www.fnal.gov/docs/products/ups/ReferenceManual/html/manpages.html
2012-06-22 18:40:11 -05:00
Joel Martin e295098330 Fix wrap mode when used with --web option.
- The --web option changes directory so the wrap mode needs to get an
  absolute path to the rebinder.
- Also, use long instead of int in rebind.c so avoid compile warnings.
2012-05-31 09:20:01 -05:00
Joel Martin cddc1613ff Fixup bugs from merge (pull #46).
- Rename unix socket option to '--unix-target' to be consistent with
  '--ssl-target' which is an analogous switch.
- Fix normal socket target mode which was broken after merge.
- Normalize/fix output for SSL, unix socket and wrap command modes.
2012-05-31 09:17:51 -05:00
Joel Martin 233b622e47 Merge pull request #46 from cloud9ers/master
Adding support for unix sockets as target socket.
2012-05-30 07:22:29 -07:00
Karim Allah Ahmed c7ba8c7826 Merge with kanaka's mainstream master branch 2012-05-28 13:09:07 +02:00
Joel Martin 89d2c92474 Move SSL target support into websocket.py.
This is cleanup related to:
https://github.com/kanaka/websockify/pull/45
2012-05-23 09:20:08 -05:00
Joel Martin d24f474362 Merge pull request #45 from d4nshields/master
feature from issue #8: Support connecting to SSL/TLS target socket
2012-05-23 06:47:14 -07:00
Karim Allah Ahmed f3054df53a Adding TCP_NODELAY to the source sockets 2012-05-22 16:49:00 +02:00
Karim Allah Ahmed c8018f29c9 Adding support for proxying from a unix socket 2012-05-22 16:09:07 +02:00
Daniel Shields 763d2d7c1c Feature: target_host is wrapped in SSL using --ssl-target option 2012-05-20 13:58:45 -04:00
Joel Martin e1c206b315 Release version 0.1.0 2012-05-11 12:12:50 -05:00
Joel Martin 63600bf422 Fix return code when client closes. 2012-05-10 22:00:27 -05:00
Joel Martin 19a9730744 Make CClose exception work in python 2.4.
Fixes https://github.com/kanaka/websockify/issues/41
2012-05-10 08:04:30 -05:00
Joel Martin 7a4dbad3e8 Fix latency test.
For echo/latency tests default to current host:port or URL.
2012-04-25 13:44:37 -05:00
Joel Martin 9a88f1800c Better close code/reason handling. 2012-04-25 13:44:01 -05:00
Joel Martin 37c0c80a93 C websockify: add --run-once option. 2012-04-13 10:36:16 -05:00
Joel Martin aef7ab3a57 Clean socket shutdown in C version too.
Related to https://github.com/kanaka/noVNC/issues/58 (supporting Apple
Remote Desktop).
2012-03-23 12:17:50 -05:00
Joel Martin 27c3da1908 Fix feature matrix link and clarify paragraph. 2012-02-23 17:45:27 -06:00
Joel Martin 9fcd92c39a Remove copy of kumina implementation.
The canonical location is https://github.com/kumina/wsproxy

There are now several external implementations of Websockify that
I link to from
https://github.com/kanaka/websockify/wiki/Feature_Matrix
2012-02-23 17:18:10 -06:00
Joel Martin 7ea468b5d7 Node impl to use einaros/ws and support HyBi.
Also adds web serving functionality and Flash policy service.
2012-02-23 17:06:35 -06:00
Joel Martin 9decfe1c95 Don't swallow SSL EOF errors. 2012-02-20 16:34:30 -06:00
Joel Martin cb839e85c4 Pull base64.js from noVNC.
Better illegal character debug output.
2012-02-20 15:49:18 -06:00
Joel Martin 31716a7265 Merge pull request #31 from SlapOS/master
Eggify websockify
2012-02-18 12:53:04 -08:00
Cédric de Saint Martin 301f3ae580 Eggify websockify 2012-02-18 09:43:12 +01:00
Joel Martin db17151941 Sync include/webutil.js with noVNC. 2012-02-14 17:37:01 -06:00
Joel Martin 7d44853da7 Pull include/util.js from noVNC. Add map to arrays for IE9.
IE9 still doesn't support [].map() so add it to the prototype in
include/util.js.
2012-02-14 07:51:44 -06:00
Joel Martin b405cdae7b Rename client.html to simple.html 2012-02-09 17:47:22 -06:00
Joel Martin e02b698015 Add simple client: tests/client.html. 2012-02-09 17:46:47 -06:00
Joel Martin bea32aebed Handle partial HyBi client frames. Cleanup buffer names.
Significant refactor of decode_hybi() and use of it in do_proxy().
2012-02-03 11:55:03 -06:00
Joel Martin bc1ea59867 Fix response to empty close frame. 2012-02-02 11:06:19 -06:00
Joel Martin b76c357f3f Fix --ssl-only option. 2012-02-02 08:11:06 -06:00
Joel Martin 8e95f18f99 Add openssl cert generation procedure to README. 2012-02-02 07:05:55 -06:00
Joel Martin 27ec5cff89 Remove more wswrapper Makefile references. 2012-02-02 06:51:39 -06:00
Joel Martin e2497313f5 Remove pointless md5_test.c file. 2012-02-01 19:17:56 -06:00
Joel Martin 04b3b2057c HyBi/IETF 6455 support to C websockify.
It's probably broken and it's definitely still messy in several ways,
but basic tests work with Chrome.

Several other C websockify cleanups:

- Remove most of the non-thread safe global variable usage (still
  a little bit that could be fixed so that threading would be easier).

- Remove wswrapper. It is unmaintained, out of date, and never worked
  well anyways (since it really needed a way to do asynchronous queued
  work but it was running in another process context making that
  hard).

- Use md5 routines from openssl.

- Remove md5.c and md5.h since no longer needed.

Thanks to https://github.com/dew111 for spurring me on to get this
done by writing code. I didn't end up using much his forked code, but
having something there goaded me enough to just get it working.
2012-02-01 19:10:39 -06:00
Joel Martin b2940c035f Show SSL error string. 2012-01-31 15:20:57 -06:00
Joel Martin 9ed4a17d70 Move alternate implementation data to wiki. 2012-01-30 15:00:58 -06:00
Joel Martin 6549c04fae Ignore clojure/lein artifacts. 2012-01-30 13:40:55 -06:00
Joel Martin 2c053f349c Clojure websockify: -main and command line args.
Can now be launched like so:

lein run websockify --web ../../noVNC/ 6080 localhost:5901
2012-01-30 13:38:18 -06:00
Joel Martin f2f838f7e2 Split generic websocket code out from websockify.
Generic TCP client and Websocket server code is now split out from the
websockify specific code.
2012-01-27 16:01:17 -06:00
Joel Martin 3278905ead Better error handling in Clojure Websockify.
Also, disable verbose debug.
2012-01-27 15:37:35 -06:00
Joel Martin a5d4fe1d18 Working vesrion Clojure Websockify.
Still needs some cleanup related to cleaning up client and target
connections.
2012-01-27 15:14:45 -06:00
Joel Martin 297a818066 Working Clojure Netty client code. 2012-01-27 13:11:38 -06:00
Joel Martin 9aa2844856 Switch to Jetty for Clojure WebSocket support.
This current code accepts WebSocket connections and can send data back
and forth.
2012-01-26 15:36:58 -06:00
Joel Martin 0664584843 Clojure Websockify using Aleph - broken. 2012-01-26 15:31:21 -06:00
Joel Martin 3aedd64765 Add websockify.py symlink for Windows support. 2012-01-05 12:00:22 -06:00
Joel Martin 7e6550806f Switch tests/echo.html to use websock.js. 2012-01-03 07:41:54 -07:00
Joel Martin e02c62932b README: websockify.rb support HyBi. 2011-12-23 10:59:56 -07:00
Joel Martin d5c94db054 Support python 3 with SSL/TLS connections.
Need to detect leading TLS/SSL character by number too for python 3.
2011-12-15 15:35:11 -06:00
Joel Martin 008a5118e7 Add commented out web-socket-js Flash debug var. 2011-12-15 15:10:09 -06:00
Joel Martin 7e2784bfcc Merge remote branch 'snorkeyg/master' 2011-11-04 10:16:17 -05:00
Joel Martin 669f77edb0 Merge commit 'e69a8d89c2354c146fa8969a142e0244be5b229a'
Pruned binary files.
2011-11-04 10:14:40 -05:00
Chris Gordon e80327ac2f Update Windows/Windows Service Readme.txt 2011-11-04 14:01:07 +10:00
Chris Gordon a487e2afa7 Update Windows/Windows Service Readme.txt 2011-11-04 14:00:54 +10:00
Chris Gordon e69a8d89c2 Windows websocket server service wrapper.
Signed-off-by: Chris Gordon <snorkeyg@gmail.com>
2011-11-04 13:52:18 +10:00
Joel Martin 545b6c80de Update kumina with HyBi-10+ support.
Pull 63aa9ce07 from https://github.com/kumina/wsproxy
2011-10-25 17:02:04 -05:00
Joel Martin 40868636da Link to API page. Default length for rQshift*
If no length parameter is given to rQshiftStr or rQshiftBytes, then
the all remaining data (the full length) will be shifted off.

Also, honor the window.WEB_SOCKET_FORCE_FLASH variable to force
web-socket-js to be used even if the browser has native WebSockets
support.
2011-10-06 16:55:10 -05:00
Joel Martin f69ac8e0a0 Clarify protocol/binary issues. 2011-10-06 10:56:36 -05:00
Joel Martin eac2c9fadd Use detection rather than python version checking.
Try importing from the newest location/name and then fallback if that
fails instead of using python version switches.

Still use version switch for the buffer/bytes to string wrapper
routines since python 2.6 has intermediate support for buffer/bytes
and I want to know if full support (ala python 3.0) is there.
2011-10-06 09:37:09 -05:00
Joel Martin 1658649d0c Merge pull request #12 from tomas-edwardsson/master
Python older than 2.5 fails, struct.unpack_from not available
2011-10-06 07:33:39 -07:00
Tomas Edwardsson 74fd12a7ae Added struct.unpack_from for python older that 2.5 2011-10-06 10:25:37 +00:00
Joel Martin acacb4527d HyBi and threading support to ruby websockify. 2011-10-05 17:53:36 -05:00
Joel Martin 6b9d6c39be Add ruby version of websockify.
Initial version is very basic but works: Hixie-76 only, no embedded
webserver, no SSL, etc.
2011-10-04 01:20:14 -05:00
Joel Martin 55e57c2048 Fix VNCAuthProxy reference. 2011-09-29 16:17:16 -05:00
Joel Martin 6748098152 Reference VNCAuthProxy in implementation list. 2011-09-29 16:15:15 -05:00
Joel Martin 724aa3aca0 HyBi fallback when no numpy. Python 3 close fix.
- Use array module for unmasking HyBi when no numpy module is
  available.

- Detect client close properly when using python 3.

- Print request URL path is specified.
2011-09-29 16:08:28 -05:00
Joel Martin 0f8b7580c6 Put include/util.js above include/websock.js.
websock.js uses Util so it needs to included first.
2011-09-23 12:09:16 -05:00
Joel Martin 636aba62ed Add --run-once and --timeout TIME parameters.
- --run-once will exit after handling a single WebSocket connection
  (but not ater flash policy or normal web requests).

- --timeout TIME will stop listening for new connections after exit
  after TIME seconds (the master process shuts down). Existing
  WebSocket connections will continue but once all connections are
  closed all processes will terminate.
2011-09-22 15:52:02 -05:00
Joel Martin 1c39c7f1f0 Fix python3 numpy buffer/string issue.
Simpler fix for this issue:
https://github.com/kanaka/websockify/pull/9

Use consistent string/byte type for HyBi decode with numpy.
2011-09-10 15:57:08 -05:00
Joel Martin 6e263063c2 Support HyBi 13.
Minor change to handshake (Sec-WebSocket-Origin renamed to Origin).

Reported version is 13 (bumped up from 8).
2011-08-31 18:05:03 -05:00
Joel Martin ada02f2c03 websocket.py: silence "Partial unmask" debug. 2011-08-31 15:36:36 -05:00
Joel Martin 0da91c7fdb Fix payload length off-by-one calculation. 2011-08-31 12:40:00 -05:00
Joel Martin 86af0b614d Fix HyBi support on 64-bit systems.
https://github.com/kanaka/noVNC/issues/76

- cleanup/update TODO.
- remove explicit check for ctypes module for HyBi.
2011-08-24 13:23:15 -05:00
Joel Martin 2e00f96431 Fix for python 2.4
Use rsplit(':', 1) instead of rpartition(':') in port argument
processing.

python2.4 may or may not work with HyBi which requires the numpy and
ctypes modules.
2011-08-10 17:48:33 -05:00
Joel Martin 4a84ab3777 More fighting with formating. 2011-08-04 11:13:28 -05:00
Joel Martin 1f7a87ecee Grr, links can't be in table fields apparently. 2011-08-04 11:12:57 -05:00
Joel Martin 7b496ce5bc Clarify that we support HyBi 07-10.
HyBi 07 reports version 7 in the handshake.
HyBi 08-10 report version 8 in the handshake.

Remove version 9 since that is not yet actually defined.
2011-08-04 11:09:12 -05:00
Joel Martin 475cfae4e5 Catch Mozilla prefixing of WebSocket.
In Firefox 7 Mozilla has added Websockets support but prefixed the
constructor with "Moz".
2011-08-02 07:59:37 -05:00
Joel Martin f1c8223a51 websocket.py: show web root, remove execute perm. 2011-07-14 15:55:26 -05:00
Joel Martin 80e1c38dd5 README: session recording no longer broken. 2011-07-14 12:32:06 -05:00
Joel Martin 6d5a137970 README: cleanup. 2011-07-14 12:30:07 -05:00
Joel Martin 6a7b56d56f READMEs: kumina features, clarifications. 2011-07-14 12:27:04 -05:00
Joel Martin 108b617eef Note kumina license, and link to kumina blog post.
Ed Schouten blog article:
http://blog.kumina.nl/2011/06/proxying-and-multiplexing-novnc-using-wsproxy/

Also, clarify external code licenses.
2011-07-13 13:01:03 -05:00
Joel Martin 9c2a41fe0e Merge commit 'kumina/master'
Conflicts:

	wsproxy.c

Conflicts:
	.gitignore
	Makefile
	README.md
2011-07-11 19:14:11 -05:00
Joel Martin 46e2fbee5f Replace addrinfo with socket() static method.
WebSocketServer.socket() is a static method takes a host and port and
an optional connect parameter. If connect is not set then it returns
a socket listening on host and port. If connect is set then
a connection will be made host and port and the socket returned. This
has IPv6 support like the addrinfo method it replaces.

Also, prefer IPv4 resolutions if they are in the list. This can be
overriden to prefer IPv6 resolutions for the same host using the
optional prefer_ipv6 parameter.
2011-07-09 13:34:53 -05:00
Joel Martin 7ae8711dc6 IPv6 and HyBi fixes.
- fix addrinfo to accept empty host as localhost

- use correct host variable in addrinfo error message

- accept HyBi 7, 8 and 9. No difference for now.

- send close buffer correctly.
2011-07-07 15:13:02 -05:00
Joel Martin 247b74950d Minor cleanup of IPv6 support code.
- Use self for static method call.

- Remove extraneous spaces.
2011-07-07 11:45:19 -05:00
Joel Martin e11012437a Merge pull request #5 from desaintmartin/master
Add support for IPv6
2011-07-07 09:19:46 -07:00
Ed Schouten d0e1fe6a3c Remove a faulty attribution from the Copyright.
The Copyright notice was copied from another source file, where I only
changed the Copyright line at the top.
2011-06-29 23:48:15 +02:00
Joel Martin 367ebb5597 Reformat feature table for readability/expansion. 2011-06-29 10:53:13 -05:00
Ed Schouten 8039dddced Add monitoring support to wsproxy. 2011-06-29 11:07:31 +02:00
Vivien Alger 78697b9663 Added static method addrinfo() 2011-06-29 10:19:52 +02:00
Joel Martin b590289de5 Remove extraneous question mark.
Part of https://github.com/kanaka/noVNC/issues/69
2011-06-28 16:28:42 -05:00
Joel Martin 9a2b50d80b Only append random string to swf path in IE.
Issue https://github.com/kanaka/noVNC/issues/69

Thanks https://github.com/EdSchouten for the catch.
2011-06-28 16:21:15 -05:00
Ed Schouten 306eab28da Add README. 2011-06-28 16:41:31 +02:00
Ed Schouten 7057e31fa0 Add support for Flash headers. This makes wsproxy work with Firefox. 2011-06-28 15:41:06 +02:00
Ed Schouten 631c5990f7 Remove all casting from the sockaddr code. 2011-06-28 12:20:21 +02:00
Ed Schouten d97d1b72d7 Add copy of strndup() for Lenny. 2011-06-28 12:11:35 +02:00
Ed Schouten c42612643a Add Debian package infrastructure and license. 2011-06-28 12:05:50 +02:00
Ed Schouten 52b07abe21 Prevent division by zero. 2011-06-28 11:46:59 +02:00
Ed Schouten 2aa2376e3a Add initial version of wsproxy source code. 2011-06-28 11:44:35 +02:00
Algervivien 30681a7018 Use of socket.getaddrinfo() to replace ipv6 attributes. Corrected error with ssl-only option 2011-06-27 18:49:01 +02:00
Algervivien 077279fe0f Refactoring of parsing 2011-06-27 17:07:29 +02:00
Algervivien eb62b2af6e Added data attributes and ipv6 condition for target 2011-06-27 11:01:01 +02:00
Algervivien a09d18b234 Added ipv6 related attributes 2011-06-27 10:21:20 +02:00
Algervivien 8d71c243b1 Modified parsing for ipv6 support 2011-06-27 09:45:49 +02:00
Joel Martin 7f487fdbd5 Fix recording, generic and part of websocket.py.
WebSocketServer(...,  record='FILE_PREFIX')

The reocrd parameter will turn on recording of all messages sent
to and from the client. The record parameter is a file prefix. The
full file-name will be the prefix with an extension '.HANDLER_ID'
based on the handler ID.

Recording required some restructing of the encode and decode function
to return more information so that the recording functions can record
just the payload data and ignore the WebSockets framing/headers.

Caveats:
- Not all messages recorded as sent to the client were necessarily
  received by the client. For example, if several messages are queued
  for the client, but the connection is shutdown before the messages
  are actually sent, these queued messages will still appear in the
  recording.
- If the server is also handling HTTP requests then the handler ID
  extensions for the recorded files will be monotonic but not
  contiguous because only WebSocket connections are recorded, not HTTP
  requests.
2011-06-26 13:55:52 -05:00
Joel Martin d91d89167f Do socket shutdown() of target before close(). 2011-06-26 13:26:59 -05:00
Algervivien 8ae73adbb7 Corrected wrong INET type in else condition 2011-06-24 19:01:47 +02:00
Cédric de Saint Martin d473f4b6d1 Use ipv6 socket when requested 2011-06-24 18:30:11 +02:00
Joel Martin c659bcb79e Refactor optional imports, make 'resource' optional.
Ticket #2: https://github.com/kanaka/websockify/issues/2 - win32
support. The 'resource' module is not available under Windows. We only
use it for daemonizing so make it optional and disable daemonizing
support on Windows for now.

Also, refactor how the optional imports to turn them into data instead
of code and iterate through them.

Add early warnings to indicate when modules are missing and
functionality is disabled.
2011-05-18 15:52:39 -05:00
Joel Martin c8587115bc Python 3.0 support. Use multiprocessing module.
Multiprocessing:
- Switch to using multiprocessing module for python >= 2.6. For python
  2.4 continue to use the os.fork() method.
- Move the new_client creation into top_new_client method to enable
  multiprocessing refactor.
- Only do SIGCHLD handling for os.fork/python 2.4. When doing our own
  SIGCHLD handling under python 3.0, we can run into a python futex
  hang when reloading a web page rapidly. Multiprocessing does it's
  own child reaping so we only need it with os.fork().

Python 3.0:
- Modify imports to reflect new locations: StringIO from io,
  SimpleHTTPRequestHandler from http.server, urlsplit from
  urllib.parse.
- Convert all print statements to print() calls. This also means no
  comma parameter idiom and only using string formatting.
- Define b2s (bytes-to-string) and s2b (string-to-bytes) which are
  no-ops on python versions prior to python 3. In python 3 these do
  the conversion between string and bytes.
- Use compatible try/except method. Exception variable must be
  extracted using sys.exc_info() rather than as part of the except
  statement.

Python 2.4:
- Now degrades more gracefully if ssl module is not found. It will
  still run, but will refuse SSL connections.
- Doesn't support HyBi-07 version due to numpy and struct.unpack_from
  requirement.
2011-05-18 11:09:10 -05:00
Joel Martin 85f84ef280 Refactor HTTP request/upgrade handling.
Instead of doing crazy things with file-descriptors in
SplitHTTPHandler, WSRequestHandler detects a WebSockets upgrade and
returns 101 as the 'last_code'. In addition to avoiding funkiness with
file-descriptors, this allows use of the already parsed headers and
removal of the parse_handshake routine.

This also makes it easier to explore adding python 3.X support
(https://github.com/kanaka/websockify/issues/1) since the
file-descriptor/string splitting is very difficult to integrate with
python 3.X.
2011-05-17 12:08:30 -05:00
Joel Martin 284ef3cc1a Send 'base64' sub-protocol. JSLint.
- Also report back sub-protocol that the server chooses.
2011-05-11 15:14:46 -05:00
Joel Martin 8c3fc55124 Extract close code and reason in decode_hybi.
Also, make it a bit more robust if no code and/or reason is given.
2011-05-02 16:50:17 -05:00
Joel Martin a339a4856a Stop sending empty frames. 2011-05-02 15:15:08 -05:00
Joel Martin c4b6e77127 README.md: formatting, note broken recording. 2011-05-01 22:30:26 -05:00
Joel Martin d82aeac93a README.md: note protocols supported by each variant. 2011-05-01 22:26:59 -05:00
Joel Martin 88b71ce171 Refactor and add IETF-07 protocol version support.
- Add initial IETF-07 (HyBi-07) protocol version support. This version
  still uses base64 encoding since the API for binary support is not
  yet finalized.

- Move socket send and recieve functions into the WebSocketServer
  class instead of having the sub-class do this. This simplifies
  sub-classes somewhat. The send_frame routine now returns the number
  of frames that were unable to be sent. If this value is non-zero
  then the sub-class should call again when the socket is ready until
  the pending frames count is 0.

- Do traffic reporting in the main class instead.

- When the client is HyBi style (i.e. IETF-07) then use the
  sub-protocol header to select whether to do base64 encoding or
  simply send the frame data raw (binary). Update include/websock.js
  to send a 'base64' protocol selector. Once the API support binary,
  then the client will need to detect this and set the protocol to
  'binary'.
2011-05-01 22:17:04 -05:00
Joel Martin ff470ad704 Make daemonize a real static method.
Add chdir option that defaults to '/' instead of passing self and
referencing self.web.
2011-04-30 16:34:56 -05:00
Joel Martin 65c1d8073c Update TODO. Add 'websockify' as protocol. 2011-04-26 09:16:03 -05:00
Joel Martin 2bb1252666 Save handshake headers and path.
Derived classes will almost certainly want to make use of the raw
info.
2011-04-19 09:36:42 -05:00
Joel Martin 7307be683f Fix chdir call to use string instead of character. 2011-04-12 22:46:32 -05:00
Joel Martin 7858c194ca Merge commit 'ccustine/master' 2011-04-12 22:46:03 -05:00
Joel Martin 76e25898bb Couple of misc utf8, base64 python tests. 2011-04-12 22:39:28 -05:00
Chris Custine 82d35c619c Include unistd.h to compile websockify on Mac OS X 2011-04-10 23:37:29 -06:00
Joel Martin 8765971e06 Use /usr/bin/env shebang to make more crossplatform.
Based on noVNC pull request from Decorum.
2011-03-26 15:27:08 -05:00
Joel Martin 7534574a2f Update web-socket-js to bb5797cad.
Primary change is removal of FABridge interface.

Seems to improve overall latency by perhaps 10%. Also, the slowdown
over time in Opera is about half as bad (but still there).
2011-03-16 10:22:31 -05:00
Joel Martin fe6b1f9e7f Pull JSLint'ing from noVNC. 2011-03-15 11:37:59 -05:00
Joel Martin 6954e4641d Better reaper, catch occasional bad WS header line.
Call waitpid in loop to catch SIGCHLD signals that happen while
handling the original SIGCHLD signal.
2011-02-01 10:46:28 -06:00
Joel Martin 0a2f850267 Reap websockify zombies. Add IE9 fix for websock.js.
Reap websockify zombies. Fixes:
https://github.com/kanaka/noVNC/issues#issue/47. Thanks NeilW.

Changes to get web-socket-js to work with IE9. Right now it's a hack to get
around: https://github.com/gimite/web-socket-js/issues#issue/41. The hack is to
disable caching of the flash objects by appending "?" + Math.random() to the
end of the flash object path (but only when using IE).
2011-01-31 10:34:42 -06:00
Joel Martin 58995c6f10 Typo. 2011-01-23 20:00:08 -06:00
Joel Martin 49b47baf13 Add some notes about the methodology of the test data. 2011-01-23 19:58:27 -06:00
Joel Martin cbc01b3f16 Re-order and fix sections. 2011-01-23 19:52:31 -06:00
Joel Martin 3d91fd3492 Use websock.js in latency test. Fixes for Opera.
Convert latency test to use include/websock.js instead of direct
WebSockets handling.

Add support for configuring the maximum bufferedAmount. This allows us
to configure it high enough to get around a bug in bufferedAmount
reporting in Opera.

Add some latency test results for Opera 11 with WebSockets turned on.
2011-01-23 19:30:51 -06:00
Joel Martin 307dda1ad0 Tolerate some bufferedAmount and send() return value.
- Only delay sending data if bufferedAmount is greater than 1000.

This seems to match the intention of the spec better. bufferedAmount
does not mean that we can't send, it's just an indication that the
network is becoming saturated. But Opera 11 native WebSockets seems to
have a bug that bufferedAmount isn't set back to zero correctly so

- websock.send returns true/false.

If all send data was flushed from the send queue then return true,
otherwise false. This doesn't mean the data won't be sent, just that
it wasn't sent this time and is queued.
2011-01-23 19:23:28 -06:00
Joel Martin d8c90aea88 Fix web-socket-js commit hash. 2011-01-19 15:35:21 -06:00
Joel Martin 70cef27dbe Add latency test and browser latency test results. 2011-01-19 15:25:44 -06:00
Joel Martin 4a09e6655e Fix firefox 4 strict complaint. 2011-01-19 15:13:36 -06:00
Joel Martin 3fa7b532b8 Update to gimite/web-socket-js 20f837425d4.
20f837425d4 changes to a single event stream handler fixing the
recursive call errors in firefox and Opera.

Also, pull web-socket-js fix from noVNC

    Related to this issue:
    https://github.com/gimite/web-socket-js/issues/#issue/50

    This prevents the "Uncaught exception: TypeError:
    'this.__handleEvents' is not a function" everytime the timer fires.
2011-01-19 15:10:55 -06:00
Joel Martin 6ff5dfa02d Strip "ws" from test names. Update TODO.
Also, rename wstest to load.
2011-01-19 13:19:47 -06:00
Joel Martin 9c4cf4ada2 Do not hang on non-ready client connection.
Wait 3 seconds for the client to send something. If no data is
available within 3 seconds then close the connection. It's probably
a non-WebSockets client that is waiting for the server to say
something first.
2011-01-13 12:22:22 -06:00
Joel Martin 046e22ea00 Only disable local echo if server is doing echo.
This makes the client usable for other plain text services that telnet
clients can normally communicate with (IRC, SMTP, etc).
2011-01-13 12:19:47 -06:00
Joel Martin 77e12cd586 Make wstelnet.html more prominent earlier. 2011-01-13 00:53:08 -06:00
Joel Martin bc96026fbf Convert wstelnet to use Websock. 2011-01-13 00:28:22 -06:00
Joel Martin 124f28c63a include/websock.js: client library for websockify.
The Websock object from websock.js is similar to the standard
WebSocket object but Websock enables communication with raw TCP
sockets (i.e. the binary stream) via websockify. This is accomplished
by base64 encoding the data stream between Websock and websockify.

Websock has built-in receive queue buffering; the message event
does not contain actual data but is simply a notification that
there is new data available. Several rQ* methods are available to
read binary data off of the receive queue.
2011-01-13 00:17:01 -06:00
Joel Martin 6d1e216115 fork noVNC, rename to websockify, cleanup.
Split of wsproxy from noVNC and rename it websockify.
2011-01-12 18:09:54 -06:00
Joel Martin 932e7318b9 Minor correct to wstelnet.js header comment. 2011-01-12 16:55:31 -06:00
Joel Martin f2538f337d wsproxy, wstelnet: wrap command, WS telnet client.
wswrapper:

    Getting the wswrapper.c LD_PRELOAD model working has turned out to
    involve too many dark corners of the glibc/POSIX file descriptor
    space. I realized that 95% of what I want can be accomplished by
    adding a "wrap command" mode to wsproxy.

    The code is still there for now, but consider it experimental at
    best. Minor fix to dup2 and add dup and dup3 logging.

wsproxy Wrap Command:

    In wsproxy wrap command mode, a command line is specified instead
    of a target address and port. wsproxy then uses a much simpler
    LD_PRELOAD library, rebind.so, to move intercept any bind() system
    calls made by the program. If the bind() call is for the wsproxy
    listen port number then the real bind() system call is issued for
    an alternate (free high) port on loopback/localhost.  wsproxy then
    forwards from the listen address/port to the moved port.

    The --wrap-mode argument takes three options that determine the
    behavior of wsproxy when the wrapped command returns an exit code
    (exit or daemonizing): ignore, exit, respawn.

    For example, this runs vncserver on turns port 5901 into
    a WebSockets port (rebind.so must be built first):

        ./utils/wsproxy.py --wrap-mode=ignore 5901 -- vncserver :1

    The vncserver command backgrounds itself so the wrap mode is set
    to "ignore" so that wsproxy keeps running even after it receives
    an exit code from vncserver.

wstelnet:

    To demonstrate the wrap command mode, I added WebSockets telnet
    client.

    For example, this runs telnetd (krb5-telnetd) on turns port 2023
    into a WebSockets port (using "respawn" mode since telnetd exits
    after each connection closes):

        sudo ./utils/wsproxy.py --wrap-mode=respawn 2023 -- telnetd -debug 2023

    Then the utils/wstelnet.html page can be used to connect to the
    telnetd server on port 2023. The telnet client includes VT100.js
    (from http://code.google.com/p/sshconsole) which handles the
    terminal emulation and rendering.

rebind:

    The rebind LD_PRELOAD library is used by wsproxy in wrap command
    mode to intercept bind() system calls and move the port to
    a different port on loopback/localhost. The rebind.so library can
    be built by running make in the utils directory.

    The rebind library can be used separately from wsproxy by setting
    the REBIND_OLD_PORT and REBIND_NEW_PORT environment variables
    prior to executing a command. For example:

        export export REBIND_PORT_OLD="23"
        export export REBIND_PORT_NEW="65023"
        LD_PRELOAD=./rebind.so telnetd -debug 23

    Alternately, the rebind script does the same thing:

        rebind 23 65023 telnetd -debug 23

Other changes/notes:

- wsproxy no longer daemonizes by default. Remove -f/--foreground
  option and add -D/--deamon option.

- When wsproxy is used to wrap a command in "respawn" mode, the
  command will not be respawn more often than 3 times within 10
  seconds.

- Move getKeysym routine out of Canvas object so that it can be called
  directly.
2011-01-12 13:15:11 -06:00
Joel Martin 86725f9b4c wswrapper: add dup2, fix select w/ NULL timeout.
- add dup2 functionality. This requires adding a ref cnt to the
  _WS_connections structure so that we only free the structure once
  all dup'd referenced are closed. Also, refactor malloc and free of
  connection structure into _WS_alloc and _WS_free.
- allow select to accept a NULL timeout value which means sleep
  forever instead of segfaulting.
- fix some compile warnings related to ppoll definition.
- move some WebSockets related html test pages into utils and symlink
  them from tests.
2011-01-08 21:46:36 -06:00
Joel Martin 6a88340929 Refactor and cleanup websocket.py and deps.
Moved websocket.py code into a class WebSocketServer. WebSockets
server implementations will sub-class and define a handler() method
which is passed the client socket after. Global variable settings have been
changed to be parameters for WebSocketServer when created.

Subclass implementations still have to handle queueing and sending but
the parent class handles everything else (daemonizing, websocket
handshake, encode/decode, etc). It would be better if the parent class
could handle queueing and sending. This adds some buffering and
polling complexity to the parent class but it would be better to do so
at some point. However, the result is still much cleaner as can be
seen in wsecho.py.

Refactored wsproxy.py and wstest.py (formerly ws.py) to use the new
class. Added wsecho.py as a simple echo server.

- rename tests/ws.py to utils/wstest.py and add a symlink from
  tests/wstest.py

- rename tests/ws.html to tests/wstest.html to match utils/wstest.py.

- add utils/wsecho.py

- add tests/wsecho.html which communicates with wsecho.py and simply
  sends periodic messages and shows what is received.
2011-01-08 15:29:01 -06:00
Joel Martin 6ace64d3ae utils/README.md: horizontal looks better.
Flip table back to be horizontal. More readable.
2011-01-06 19:21:17 -06:00
Joel Martin 90966d6251 utils/README.md: flip table. Add web server info.
Flip the feature table to be tall instead of wide.

Added row about "web server" functionality in wsproxy.py.
2011-01-06 19:17:32 -06:00
Joel Martin 9aaf26e878 Merge branch 'master' of git@github.com:kanaka/noVNC 2011-01-06 19:13:39 -06:00
Joel Martin 02a7dd2c29 Merge branch 'master' of git@github.com:kanaka/noVNC 2011-01-06 17:33:22 -07:00
Joel Martin 96bc3d3088 wsproxy.py: add web serving capability.
- Added ability to respond to normal web requests. This is basically
  integrating web.py functionality into wsproxy. This is only in the
  python version and it is off by default when calling wsproxy. Turn
  it on with --web DIR where DIR is the web root directory.

Next task is to clean up wsproxy.py. It's gotten unwieldy and it
really no longer needs to be parallel to the C version.
2011-01-06 18:26:54 -06:00
Joel Martin 58dc1947de wsproxy: warn when no cert. C sock close cleanup.
Warn early about no SSL cert and add clearer warning when a connection
comes in as SSL but no cert file exists.

For the C version, cleanup closing of the connection socket. Use
shutdown for a cleaner cleanup with the client.
2011-01-04 13:14:46 -06:00
Joel Martin 58da507bb8 README: add companies/projects using noVNC. 2011-01-04 12:19:54 -06:00
Joel Martin 9b940131d3 include/canvas.js: show full user agent in console. 2011-01-04 10:30:26 -06:00
Joel Martin e3716842ef include/rfb.js: show Flash version in console. 2011-01-04 10:27:25 -06:00
Joel Martin bf5ee68828 Expose getKeysym and add keyboard test.
Related to issue Non-US keyboard layout option issue:
https://github.com/kanaka/noVNC/issues#issue/21
2011-01-03 12:34:41 -06:00
Joel Martin 2574936f60 utils/README.md, docs/TODO, docs/notes: updates.
Add wswrapper info to utils/README.md and docs/TODO. Remove innacurate
info from docs/notes.
2010-12-30 11:00:50 -07:00
Joel Martin 71ba9a7a54 wswrapper: update README, DO_MSG def for output.
Update README to mention wswrapper. Add DO_MSG define which controls
whether wswrapper code generates basic output.
2010-12-29 14:11:28 -07:00
Joel Martin 56d9aa816b wswrapper: interpose on poll/ppoll also.
poll/ppoll interposer builds but is untested.
2010-12-27 19:44:14 -07:00
Joel Martin 64dbc6bb63 wswrapper: timeout select.
The select call needs to timeout if a WebSocket socket keeps reporting
ready but actually isn't ready. To prevent it hanging forever in that
condition, the timeout value is now adjusted now for each call.

Move the DO_DEBUG and DO_TRACE settings to wswrapper.c.
2010-12-27 16:08:27 -07:00
Joel Martin 6b900d25d0 wswrapper: interpose select/pselect. Cleaup.
Interpose on select/pselect so that WebSockets sockets are only
reported as ready if they have enough to actually decode at least
1 byte of real data. This prevents hanging in read/recv after
WebSocket is reported as ready but is not actually ready because empty
frames or less than four base64 bytes have been received.

Split defines and constant defintions into wswrapper.h.

Cleanup debug output and add TRACE for more detailed tracing debug
output.

Major TODO is that select needs to timeout if WebSocket socket keeps
reporting ready but actually isn't ready. That condition will
currently hang forever because the select timeout value is not
adjusted when looping.
2010-12-27 13:21:07 -07:00
Joel Martin fce6ac5cb4 Fix to "Tolerate fragmented ServerInit".
Issue #39: https://github.com/kanaka/noVNC/issues/issue/39
2010-12-24 17:39:13 -07:00
Joel Martin 318d473438 Tolerate fragmented ServerInit.
Issue #39: https://github.com/kanaka/noVNC/issues/issue/39
2010-12-24 15:02:48 -07:00
Joel Martin 0f7f146f20 utils/launch.sh: find top web dir (with vnc.html). 2010-12-21 10:17:43 -06:00
Amir Malik b992f7c7dd use cd, dirname, and pwd to determine path instead of readlink (Mac fix) 2010-12-22 00:15:33 +08:00
Amir Malik a22a3cc0ea set socket option SO_REUSEADDR to prevent "Address already in use" error 2010-12-21 23:31:46 +08:00
Joel Martin 40a653f555 wswrapper: fix preload path and interpose port.
Make path to ld preload library absolute so wswrapper works even if
path is changed before main program is executed (i.e. by the vncserver
wrapper script).

bind() was using the return value for the port number, but it's
actually the original port number that we should interpose on in the
bind() routine.
2010-12-16 14:04:16 -06:00
Joel Martin b144a0933d wswrapper: Normalize comments, remove unused headers. 2010-12-14 13:14:21 -05:00
Joel Martin c99124b527 wswrapper: Allow multiple WebSockets connections.
Allocate buffer and state memory for each accepted connection. This
allows all WebSockets connections to a given listen port to be wrapped
with WebSockets support.
2010-12-14 13:14:12 -05:00
Joel Martin 70c585968b wswrap: WSWRAP_PORT envvar and wswrap script.
wswrapper.so will only interpose on the listen port specified in
WSWRAP_PORT.

Add simple wswrap script that sets the WSWRAP_PORT, LD_PRELOAD and
invokes the command line to wrap.
2010-12-13 14:20:34 -05:00
Joel Martin e46719100c Make compatible with jQuery. Slight API change.
Rename the $() selector to $D() so that it doesn't collide with
the jQuery name.

The API change is that the 'target' option for Canvas and RFB objects
must now be a DOM Canvas element. A string is no longer accepted
because this requires that a DOM lookup is done and the Canvas and RFB
should have no UI code in them. Modularity.
2010-12-10 08:25:36 -06:00
Joel Martin 5b0bbd5c12 wswrapper: wrap existing server using LD_PRELOAD.
wswrapper.so is LD_PRELOAD shared library that interposes and turns
a generic TCP socket into a WebSockets service.

This current version works but will only allow work for a single
connection, subsequent connections will not be wrapped. In addition
the wrapper interposes on the first incoming network connection. It
should read an environment variable to determine the port to interpose
on. Also, should limit origin based on another environment variable.
Then there should be a wswrap setup script that allows easier
invocation.
2010-12-02 22:11:02 -06:00
Joel Martin 79f0a095b6 rfb.js: avoid multiple b64 sequences per frame.
Only call encode_message when the WebSockets object is actually
ready to send. Otherwise multiple base64 encode sequences can be
encoded into the same WebSockets frame. This causes the C version of
wsproxy to crash and the python version to ignore the subsequent
base64 sequence(s).

Thanks to Colin Dean (xvpsource.org) for finding this and helping
track it down.
2010-11-15 13:43:26 -05:00
Joel Martin f7ec5b2cb6 Rename default_controls.js to ui.js.
And DefaultControls to UI.
2010-11-10 16:02:19 -06:00
Joel Martin e66f3f89f2 Add Chrome Frame support. Close requests in web.py.
- Add meta tag to vnc.html and vnc_auto.html so that if Chrome Frame
  is installed, it is used.

- Add detection to default_controls.js that shows a message with
  a Chrome Frame install link if the user is using a version of IE
  without Canvas support.

- Fix web.py so that requests have their connection closed after they
  are completed.  This has been a bug for a while but it prevents
  Chrome Frame from working because Chrome Frame doesn't activate
  until the initial request connection closes.
2010-11-09 12:06:03 -06:00
Joel Martin 1ee2d93e94 wsproxy.js: Fix multi-frame decoding.
- Also, discovered node.js bug in base64 decoding. Added test case and
  filed https://github.com/ry/node/issues/issue/402
2010-11-07 22:28:08 -06:00
Joel Martin fd758dd335 First pass at wsproxy using node (node.js).
Node:
    http://nodejs.org/
    https://github.com/ry/node

It mostly works, but it eventually gets an error from the target which
is probably due to missing support for re-assembly of client
WebSockets frames.
2010-11-07 19:06:20 -06:00
Joel Martin 58b4c9408f wsproxy: Fix --key parameter use. 2010-11-06 14:12:37 -05:00
Joel Martin c1d008f1ee Fix flush with strict DOCTYPE.
- With a strict doctype, the margin size needs a "px" suffix.
2010-11-06 14:11:30 -05:00
Joel Martin cdb55d26e5 canvas.js: workaround WebKit bug, issue #28.
This is WebKit bug https://bugs.webkit.org/show_bug.cgi?id=46319

The workaround is to wrap Canvas render functions with a function that
sets a flush timer. The flush function sets the right margin and then
1ms later sets it back. This triggers the canvas to redraw with the
correct contents.

Two downsides:
- rendering is slower, but only on the busted versions of webkit.
  Correct and useful is better than fast and useless.
- There is a barely perceptible jitter of the control buttons because
  the canvas size is changing by one pixel.

To support this functionality, we also have to read out the exact
webkit version from the user agent in the render engine detection code
in include/util.js.
2010-11-06 12:23:23 -05:00
Joel Martin 455e4657f6 default_controls.js: canvas fail fix. Misc cleanup.
- Make sure that canvas exists (i.e. didn't throw an error) before
  trying to call canvas method get_canvas_uri.

- Typos in HTML render engine debug output.
2010-11-06 12:15:08 -05:00
Joel Martin 3205a3dee8 Add --key option for separate cert and key file.
If only --cert is specified then continue to assume both certificate
and key are in the same file (key first).
2010-11-06 10:55:09 -05:00
Joel Martin e70f1d947e Remove left over record code. Squelch compile warnings 2010-11-06 10:53:32 -05:00
François Revol f61274c827 wsproxy: Mac OS X build fixes
- pass CFLAGS and LDFLAGS in case one needs to use -m32
- link to libcrypto for _ERR_print_errors_fp
- __THROW is non-standard define it to nothing by default
- use b64_ntop and b64_pton instead of mangled versions, OSX doesn't mangle them in the same way
- access() takes two arguments!

Signed-off-by: François Revol <revol@free.fr>
2010-11-06 10:04:24 -05:00
Joel Martin 1f758e87d3 Issue #34: fix RFB 3.3/3.7 with no auth scheme.
- Split out ClientInitialisation state.

- In version 3.3 and 3.7, when the server has no auth (scheme
  1), then we should skip from Authentication to ClientInitialisation.
2010-10-28 16:30:41 -05:00
Joel Martin 3dc3135b21 utils/README.md: second try on cmd formatting. 2010-10-28 10:53:08 -05:00
Joel Martin 6502293f21 utils/README.md: Fix command formatting. 2010-10-28 10:52:27 -05:00
Joel Martin e5d60a8ba2 Issue #32, wsproxy README, update webkit bug info,
- Add wsproxy README.md in utils/ directory.

- Document how to build ssl module for python 2.5 and older in wsproxy
  README.

- Update browsers.md to note revision that have the webkit Canvas
  rendering bug: WebKit build 66396 through 68867 (Chrome/Chromium
  build 57968 through 61278).
2010-10-28 10:45:26 -05:00
Joel Martin f1a9971c82 Expose VNC shared mode setting in UIs.
If shared mode is false, then the server should disconnect other
connections before the current connection is allowed to proceed.
2010-10-24 18:34:50 -05:00
Joel Martin 65bca0c904 Fix style caching. Canvas cleanup from Diet-noVNC.
- Style caching gives a small performance speedup in firefox, but not
  much. Might not be worth complexity, but leave it in for now.
2010-10-18 14:30:50 -05:00
Joel Martin 028b26f14b Fix reason_len not defined bug. 2010-10-14 11:07:54 -05:00
Joel Martin ce2b6909cd rfb.js: fail() wrapper for common failed pattern. 2010-10-14 10:09:33 -05:00
Joel Martin 8b17ac27f0 Add manual flash policy socat server info. 2010-10-10 18:59:02 -05:00
Joel Martin c084c396ba utils/Makefile: clean up md5.o too. 2010-10-04 13:30:53 -04:00
Joel Martin 60440cee15 rfb.js: rQwait, cuttext simplification.
- rQwait checks the receive queue to see if there is enough data to
  satisfy the following request. If not it returns true (which is
  almost always translated into an immediate return false by the
  caller).

- rQwait is called quite a bit and this generally allows 4 lines to
  become 1 line where it is called.

- rQwait allows simplification of cuttext processing. No global
  tracking needed anymore.

Overall, about 60 lines less code.
2010-10-01 11:50:22 -05:00
Joel Martin a99959719d include/des.js: trim some fat.
DES is just used once during authentication and is not performance
sensitive so we save some space by generating and/or removing some
lookup tables. Also, shorten some very frequently used variables.

Shaves off about 100 lines.
2010-09-30 11:17:52 -05:00
Joel Martin a59f1cd269 webutil.js, util.js: split cleanup. 2010-09-29 15:05:27 -05:00
Joel Martin 5a00c9d18a Merge branch 'master' of git@github.com:kanaka/noVNC 2010-09-29 15:01:01 -05:00
Antoine Mercadal 8d5d2c8230 Split util into two file:
- util.js that contains essential functions
 - webutils.js that contains the GUI utility function.js

this helps to include noVNC in other project, especially Cappuccino Application
i
2010-09-30 03:59:56 +08:00
Joel Martin 12d2e7c192 des.js: remove decrypt and simplify.
The decrypt functionality is never used so remove it. Also, we can
assume that we are always DES encrypting 16 characters which allows
several things to be simplified in DES.

Overall this removes about 80 lines of code.
2010-09-29 14:48:19 -05:00
Joel Martin a679a97d1b Show rect/enc counts, add vnc_perf.html test.
- include/rfb.js: Keep track of the number of rects of each encoding
  type and print them out when we close a connection (if 'info'
  logging level).

- tests/vnc_perf.html: first pass at a noVNC based performance
  benchmark.

- utils/wsproxy.py: Fix the output of the record filename.
2010-09-25 15:50:43 -05:00
Joel Martin 3b20e7a90f rfb.js, canvas.js: status feedback on Canvas functionality.
Read the render mode selected by canvas and report it in the initial
page loaded status message.
2010-09-24 10:47:39 -05:00
Joel Martin 562beccf18 docs/browsers.md: noVNC webkit bug link format. 2010-09-24 10:46:59 -05:00
Joel Martin d4139a9b06 README.md: move browser page link. 2010-09-24 10:45:33 -05:00
Joel Martin 6de07adb71 README.md: add link to browsers.md, update requirements. 2010-09-24 10:29:42 -05:00
Joel Martin f01e917ecc docs/browsers.md: Separate browser support page. 2010-09-24 09:59:54 -05:00
Joel Martin ff36b1270b Refactor settings object, add connectTimeout setting.
- include/util.js: Add type and desc field to conf_default routine.
  Make comment descriptions of settings into desc parameters that can
  be queried. Also, use set_FOO in conf_default to set or coerce the
  current setting so that we always have the right type for the value.

- include/rfb.js, include/default_config.js: add connectTimeout
  setting to address situations with slow connections that may need
  more than 2 seconds.
2010-09-23 09:39:24 -05:00
Joel Martin aa78706983 rfb.js: wait for SecurityResult failure reason bytes.
Yet another weird VNC server behavior: sending a failure and length
before the reason message. To calculated the length, the reason string
is already available, why not just send everything as one packet. Oh
well.
2010-09-23 09:17:09 -05:00
Joel Martin 005d9ee999 Misc cleanup: debug logging, record filename, etc.
- include/canvas.js: When 'debug' logging, show browser detection
  values.
- test/canvas.html: Only restore the canvas to it's starting state if
  the logging level is not 'debug'.
- wsproxy.py: Append the session number to the record filename so that
  multiple sessions don't stomp on each other.
2010-09-23 08:17:00 -05:00
Joel Martin 8787e49b92 util.js: detect firefox 4.X correctly.
Update the browser detection code (from mootools) with a fix that
detects firefox 4.0 correctly.
2010-09-23 08:08:08 -05:00
Joel Martin c1eba48f79 logging: add Util.get_logging(), canvas clearing.
Only clear canvas if log level is not debug instead of using
'#__debug__' in the URL.
2010-09-22 17:11:57 -05:00
Joel Martin 57c7903f60 playback.js: move to include/ for easier reference.
Easier to reference from web site (gh-pages branch).
2010-09-22 16:55:06 -05:00
Joel Martin 31a837d55e No local cursor by default due to issues #27, #29.
In Safari, local cursor rendering is corrupt. In firefox 3.6.10, local
cursor rendering causes a segfault. Probable that the .cur format is
not 100% compliant (even though it works in Chrome and firefox 3.5 and
firefox 4.0). So just disable it by default until I can figure out how
to address the problems.
2010-09-20 16:15:40 -05:00
Joel Martin 02889945cb C proxy: Issue #14: wss:// from Safari
Addresses this issue:
http://github.com/kanaka/noVNC/issues#issue/14

This goes along with commit 7e63919e6 but for the C proxy.
2010-09-15 18:21:42 -05:00
Joel Martin 0a1184bde8 API change: add sendKey() to manually send key code.
RFB.sendKey(code, down)

If down is not specified then both a down followed by an up code will
be sent.
2010-09-15 18:14:27 -05:00
Joel Martin 7e63919e6d proxy: Issue #14: detect and allow wss:// from Safari.
Addresses this issue:
http://github.com/kanaka/noVNC/issues#issue/14

Safari starts with '\x80' rather than '\x16' like Chrome and Firefox
and having PROTOCOL_TLSv1 doesn't work with Safari. But just removing
the ssl_version allows things to work with Safari wss:// connections.

Also, if the handshake (after SSL wrapping) is null then terminate the
connection. This probably means the certificate was refused by the
client. Unfortunately Safari (the version I have) doesn't cleanly
shutdown WebSockets connections until the page is reloaded (even if
the object is no longer referenced).
2010-09-15 12:19:17 -05:00
Joel Martin e3efeb32a7 rfb.js: state refactor, add 'disconnect' state.
Add a new state 'disconnect' to reflect that we are not truly
'disconnected' until we get an onclose event. Add a disconnect timer
to match.

Handle disconnected cleanup better in updateState(). Anytime we enter
in a disconnect/disconnected state, make sure all running state is
cleaned up (WebSocket, timers, canvas).
2010-09-11 15:31:50 -05:00
Joel Martin cc374cd61a proxy: always multiprocess and add --verbose.
Always fork handlers processes. Instead printing traffic when
single-processing, print traffic if verbose flag given.
2010-09-11 15:10:54 -05:00
Joel Martin ac7bdbc22f web-socket-js (issue #37): close() when connecting
Filed this issue for this bug:
http://github.com/gimite/web-socket-js/issues/issue/37

Right now the close() call only calls __flash.close() if readyState is OPEN.
But it should really call close any time that readyState is not CLOSED or
CLOSING.

The case I ran into is when I want to do the following:
1. make a test connection
2. tell the server to setup for a connection
3. connect again

I call close on the test connection, but since it is ignored when CONNECTING,
it eventually times out with a error. But by that time I have already issued a
new connection, it causes the new connection to fail. close() should cancel
CONNECTING state too.
2010-09-11 13:52:49 -05:00
Joel Martin 071f2818a8 gimite/web-socket-js issue #35: async onclose.
Filed this bug about this issue:
http://github.com/gimite/web-socket-js/issues#issue/35

To work around the flash "recursive call" problem, WebSocket.as has
the onclose event disabled in the close() call and the javascript half
of the close() call does the onclose() call instead. This is fine, but
it needs to be asynchronous to act more like what happens with
a normal WebSockets object. The current behavior is that the onclose()
method is called inline (synchronously) when the close() is called and
this inconsistency make state handling more difficult.
2010-09-11 12:44:39 -05:00
Joel Martin edc4725260 proxy: do handshake in forked process too. 2010-09-10 14:31:34 -05:00
Joel Martin a0315ab1dc wsproxy: multiprocess capable.
Add -m, --multiprocess option which forks a handler for each
connection allowing multiple connections to the same target using the
same proxy instance.

Cleaned up the output of the handler process. Each process' output is
prefixed with an ordinal value.

Changed both the C and python versions of the proxy.
2010-09-10 13:05:48 -05:00
Joel Martin 465faf19db Remove record option from C wsproxy.
I've decided that debug/develop/extra features will just be in the
python version of the proxy. The C version (and other versions) will
just have the core functionality (unless someone wants to support it).
2010-09-10 09:58:26 -05:00
Joel Martin 5f409eeeeb License header cleanup. 2010-09-08 15:06:34 -05:00
Joel Martin 2a6018df9f web-socket-js: 9e7663771 build and remove source.
web-socket-js now has all the functionality and fixes needed for noVNC
so remove the include/as3crypto_patched directory and the
include/web-socket-js/flash-src directory (i.e. the sources for
web-socket-js). This cleans up almost 3K from the include/ directory.

Update to web-socket-js build based on upstream (gimite/web-socket-js)
9e766377188.
2010-09-08 14:57:32 -05:00
Joel Martin b5087acc24 default_controls.js: Fix cursor setting init.
The rfb variable wasn't available at the point settingsDisabled() was
being called since it was called inline with RFB() initialization. To
solve this we pass the updateState rfb variable so that the canvas can
be queried for setting the cursor_uri value.
2010-09-08 13:46:41 -05:00
Joel Martin c0f3c66489 TODO and .gitignore: updates. 2010-09-08 10:15:07 -05:00
Joel Martin d595e65685 JSLint. 2010-09-08 10:11:11 -05:00
Joel Martin 2f6a1c2bda vnc_playback.html: print frame_idx on error. 2010-09-07 16:22:28 -05:00
Joel Martin 673118fb21 Encrypt default to 'false' in vnc_auto.html also. 2010-09-07 09:57:37 -05:00
Joel Martin b8bd88d085 playback.js: realtime playback and split out code.
Preparation for online demo.

Split general playback code into tests/playback.js.

Use timestamps from recording with proxy to playback in realtime.
2010-09-01 12:31:54 -05:00
Joel Martin 975aa8c01c TODO: move long-term features to github issues. 2010-08-31 22:48:11 -05:00
Joel Martin 3afc7a2b89 Issue #15 - rfb.js: wait for security type list.
Apparently the virtualbox VNC server send the size and then the
security type list in separate frames so we need to wait for the full
list.
2010-08-31 22:22:22 -05:00
Joel Martin 3cc74720f0 canvas.js: Fix ignore for scrolled window.
When the documement/window is scrolled, the onMouseDisable routine was
not properly calculating the position to test whether to ignore the
event or not.
2010-08-31 13:36:14 -05:00
Joel Martin d67de76770 Rename tightpng img queue variable to imgQ. 2010-08-31 12:08:47 -05:00
Joel Martin 3e7a7cefc6 More timing "history" purge. 2010-08-30 15:59:53 -05:00
Joel Martin 9c57ac3985 rfb.js: JSLint'ing
Change RQ and SQ vars to rQ and sQ since caps at the start implies
a classable entity.
2010-08-30 15:57:58 -05:00
Joel Martin 0d1e1b7281 Merge init() into the constructor.
This is logical now since the external update callback can be provided
when the object is created so we don't need a separate init function.
2010-08-30 15:16:07 -05:00
Joel Martin 55dee43279 Remove psuedo-UTF8 encoding.
It's less efficient on average that base64 (150% vs 133%). It's
non-standard (0 shifted to 256 before encoding). And I rarely use it.
2010-08-27 12:10:09 -05:00
Joel Martin e8c1698995 rfb.js: remove timing history.
Turned out not to be useful (pretty much never looked at the info once
I added it). The playback test is much more useful for measuring
performance.
2010-08-27 11:29:22 -05:00
Joel Martin eabf4670fb rfb.js/tight_png: fix indexed receive queue handling.
getCLength was not using the index (RQi) into the receive queue.
2010-08-27 11:21:30 -05:00
Joel Martin 4ff85f496c Test both builtin and base64.js functions. 2010-08-26 11:34:44 -05:00
Joel Martin 67b4e9879a Indexed receive queue. Up to 2X speedup in Chrome.
Generally, most servers send hextile updates as single updates
containing many rects. Some servers send hextile updates as many small
framebuffer updates with a few rects each (such as QEMU). This latter
cases revealed that shifting off the beginning of the receive queue
(which happens after each hextile FBU) performs poorly.

This change switches to using an indexed receive queue (instead of
actually shifting off the array). When the receive queue has grown to
a certain size, then it is compacted all at once.

The code is not as clean, but this change results in more than 2X
speedup under Chrome for the pessimal case and 10-20% in firefox.
2010-08-26 10:22:29 -05:00
Joel Martin fb007628d6 Add Javascript variable container to record data.
- This allows the recorded data to be immediately usable by
  tests/vnc_playback.html
2010-08-12 09:50:49 -05:00
Joel Martin 1a5dd77d37 Treat RFB 3.6 as 3.3.
Apparently there are versions of UltraVNC that report version 3.6.
This is not a legal version according to the spec, but we'll just
force version 3.3 if we receive it. Thanks to Larry Rowe for the info.
2010-08-11 11:21:15 -05:00
Joel Martin 4ed717ad31 Scroll render test and perf speedup.
Turns out when Windows is running in QEMU and a window scroll happens,
there are lots of little hextile rects sent. This is slow in noVNC.

- Some recording/playback improvement.
- Add test harness to drive playback of recordings.
- By pulling off the rect header in one chunk we get a 3X speedup in
  Chrome and a 20% speedup in firefox (specifically for the scroll
  test).
- Also, get rid of some noise from creating timers for handle_message.
  Check to make sure there isn't already a pending timer first.
2010-08-06 16:43:24 -05:00
primalmotion b7155950d3 * take care of kanaka's suggestions
(cherry picked from commit 11f3271a52)

Signed-off-by: Joel Martin <github@martintribe.org>
2010-08-04 15:29:42 -05:00
primalmotion 6425f611d8 * Adding a way to set the DOM document to use.
This is very usefull when you need to open a new window (with a new document) from javascript,
without having to reload the script.js.
(cherry picked from commit 8ded53c1de)

Signed-off-by: Joel Martin <github@martintribe.org>
2010-08-04 15:18:17 -05:00
Joel Martin b925c96781 JSLint: use ===. 2010-08-04 15:14:40 -05:00
Joel Martin a6a1ad3d0a Remove unused imports (sys, ssl) in wsproxy.py 2010-08-04 14:33:32 -05:00
Joel Martin 5958fb4996 Python 2.4 compatible imports.
- Fallback to md5 module if hashlib not there.
- Import parse_qsl from cgi where it is in both 2.4 and 2.6
2010-08-04 14:32:10 -05:00
Joel Martin c95c24e743 Fix #19: python2.4 support.
- Replace URL parsing using "".partition() with urlparse module.
2010-08-04 14:18:55 -05:00
Joel Martin 801482be6a WebSockets orderly/clean close frame.
- When a packet with only '\xff\x00' is received, this means the
  client is doing an orderly shutdown. (WebSockets spec version 76)
2010-08-03 13:23:59 -05:00
Joel Martin 208c832b28 Encrypt default to off, TODO updates. 2010-08-03 13:20:44 -05:00
263 changed files with 5962 additions and 38258 deletions
+35
View File
@@ -0,0 +1,35 @@
name: Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-18.04
strategy:
matrix:
python-version:
- 3.4
- 3.5
- 3.6
- 3.7
- 3.8
- 3.9
fail-fast: false
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install setuptools
python -m pip install -r test-requirements.txt
- name: Install old numpy
run: |
python -m pip install 'numpy<1.17'
if: ${{ matrix.python-version >= '3.4' && matrix.python-version < '3.7' }}
- name: Run tests
run: |
python setup.py nosetests --verbosity=3
+10 -2
View File
@@ -1,4 +1,12 @@
*.pyc
*.o
wsproxy
*.DS_Store
*.so
.project
.pydevproject
target.cfg
target.cfg.d
.tox
build/
dist/
*.egg-info
View File
+124
View File
@@ -0,0 +1,124 @@
Changes
=======
0.11.0
------
* Command line now supports disabling directory listings
* Basic Dockerfile included
0.10.0
------
* Python 3.4 or newer is now required
* Empty message frames are now supported
* Tokens can now specify a Unix domain socket file to connect to
* Time limits on JWT tokens are now respected
* Whitespace is better tolerated in token files
* Lots of minor fixes...
0.9.0
-----
* Base64 support removed and binary mode is now required
* Low level WebSocket protocol handling now has its own class
* Authentication now optionally required for web server
* Server hostname can be used as the token
* JWT/JWS/JWE can be used for the token
* redis can be used for the token
* Can now log to syslog
* Improved latency by disabling Nagle for proxied connection
* Added client certificate authentication
* Support for password protected certificate key file
* TLS ciphers and options are now configurable
* Can be invoked via inetd
* Lots of minor fixes...
0.8.0
-----
* Make websockify properly terminate children on SIGTERM (#226)
* Remove logging in signal handlers (this can cause Python to hang under certain conditions) (#219)
* Make it easier to log to a file (#205)
* Add support for IPv6 addresses in tokens in the TokenFile token plugins (#197)
* Improve auth plugin framework to enable better support for HTTP auth (#194, #201)
* Fix bug in JSONTokenAPI token plugin (#192)
* Fix a missing variable in the exception handler (#178)
0.7.0
-----
* Python 3 support fixes (#140, #155, #159)
* Generic token-parsing plugins support (#162)
* Generic authentication plugins support (#172)
* Fixed frame corruption on big-endian systems (#161)
* Support heartbeats (via PING) and automatic responses to PONG (#169)
* Automatically reject unmasked client frames by default (strict mode) (#174)
* Automatically restart interrupted select calls (#175)
* Make 'run' respect environment settings (including virtualenv) (#176)
0.6.1 - May 11, 2015
--------------------
* **PATCH RELEASE**: Fixes a bug causing file_only to not be passed properly
0.6.0 - Feb 18, 2014
--------------------
* **NOTE** : 0.6.0 will break existing code that sub-classes WebsocketProxy
* Refactor to use standard SocketServer RequestHandler design
* Fix zombie process bug on certain systems when using multiprocessing
* Add better unit tests
* Log information via python `logging` module
0.5.1 - Jun 27, 2013
--------------------
* use upstream einaros/ws (>=0.4.27) with websockify.js
* file_only and no_parent security options for WSRequestHandler
* Update build of web-socket-js (c0855c6cae)
* add include/web-socket-js-project submodule to gimite/web-socket-js
for DSFG compliance.
* drop Hixie protocol support
0.4.1 - Mar 12, 2013
--------------------
* ***NOTE*** : 0.5.0 will drop Hixie protocol support
* add include/ directory and remove some dev files from source
distribution.
0.4.0 - Mar 12, 2013
--------------------
* ***NOTE*** : 0.5.0 will drop Hixie protocol support
* use Buffer base64 support in Node.js implementation
0.3.0 - Jan 15, 2013
--------------------
* refactor into modules: websocket, websocketproxy
* switch to web-socket-js that uses IETF 6455
* change to MPL 2.0 license for include/*.js
* fix session recording
0.2.1 - Oct 15, 2012
--------------------
* re-released with updated version number
0.2.0 - Sep 17, 2012
--------------------
* Binary data support in websock.js
* Target config file/dir and multiple targets with token selector
* IPv6 fixes
* SSL target support
* Proxy to/from unix socket
0.1.0 - May 11, 2012
--------------------
* Initial versioned release.
View File
-11
View File
@@ -1,11 +0,0 @@
noVNC is licensed under the LGPL version 3 (see docs/LICENSE.GPL-3 and
docs/LICENSE.LGPL-3) with the following exceptions:
include/as3crypto_patched/ : various BSD style licenses
include/base64.js : Dual GPL-2 or LGPL-2.1
incluee/des.js : Various BSD style licenses
include/web-socket.js/ : New BSD license
+1
View File
@@ -0,0 +1 @@
include CHANGES.txt README.md COPYING
+11
View File
@@ -0,0 +1,11 @@
TARGETS=rebind.so
CFLAGS += -fPIC
all: $(TARGETS)
rebind.so: rebind.o
$(CC) $(LDFLAGS) $^ -shared -fPIC -ldl -o $@
clean:
rm -f rebind.o rebind.so
+170 -210
View File
@@ -1,242 +1,202 @@
## noVNC: HTML5 VNC Client
## websockify: WebSockets support for any application/server
websockify was formerly named wsproxy and was part of the
[noVNC](https://github.com/novnc/noVNC) project.
### Description
At the most basic level, websockify just translates WebSockets traffic
to normal socket traffic. Websockify accepts the WebSockets handshake,
parses it, and then begins forwarding traffic between the client and
the target in both directions.
noVNC is a VNC client implemented using HTML5 technologies,
specifically Canvas and WebSockets (supports 'wss://' encryption).
For browsers that do not have builtin WebSockets support, the project
includes [web-socket-js](http://github.com/gimite/web-socket-js),
a WebSockets emulator using Adobe Flash .
In addition, [as3crypto](http://github.com/lyokato/as3crypto_patched)
has been added to web-socket-js to implement WebSockets SSL/TLS
encryption, i.e. the "wss://" URI scheme.
Special thanks to [Sentry Data Systems](http://www.sentryds.com) for
sponsoring ongoing development of this project (and for employing me).
### News/help/contact
Notable commits, announcements and news are posted to
@<a href="http://www.twitter.com/noVNC">noVNC</a>
<a href="http://www.twitter.com/noVNC">@noVNC</a>
If you are a websockify developer/integrator/user (or want to be)
please join the <a
href="https://groups.google.com/forum/?fromgroups#!forum/novnc">noVNC/websockify
discussion group</a>
Bugs and feature requests can be submitted via [github
issues](https://github.com/novnc/websockify/issues).
If you want to show appreciation for websockify you could donate to a great
non-profits such as: [Compassion
International](http://www.compassion.com/), [SIL](http://www.sil.org),
[Habitat for Humanity](http://www.habitat.org), [Electronic Frontier
Foundation](https://www.eff.org/), [Against Malaria
Foundation](http://www.againstmalaria.com/), [Nothing But
Nets](http://www.nothingbutnets.net/), etc. Please tweet <a
href="http://www.twitter.com/noVNC">@noVNC</a> if you do.
### WebSockets binary data
Starting with websockify 0.5.0, only the HyBi / IETF
6455 WebSocket protocol is supported. There is no support for the older
Base64 encoded data format.
### Screenshots
### Encrypted WebSocket connections (wss://)
Running in Chrome before and after connecting:
To encrypt the traffic using the WebSocket 'wss://' URI scheme you need to
generate a certificate and key for Websockify to load. By default, Websockify
loads a certificate file name `self.pem` but the `--cert=CERT` and `--key=KEY`
options can override the file name. You can generate a self-signed certificate
using openssl. When asked for the common name, use the hostname of the server
where the proxy will be running:
<img src="http://kanaka.github.com/noVNC/img/noVNC-1.jpg" width=400>&nbsp;<img src="http://kanaka.github.com/noVNC/img/noVNC-2.jpg" width=400>
```
openssl req -new -x509 -days 365 -nodes -out self.pem -keyout self.pem
```
See more screenshots <a href="http://kanaka.github.com/noVNC/screenshots.html">here</a>.
For a self-signed certificate to work, you need to make your client/browser
understand it. You can do this by installing it as accepted certificate, or by
using that same certificate for a HTTPS connection to which you navigate first
and approve. Browsers generally don't give you the "trust certificate?" prompt
by opening a WSS socket with invalid certificate, hence you need to have it
accept it by either of those two methods.
If you have a commercial/valid SSL certificate with one or more intermediate
certificates, concat them into one file, server certificate first, then the
intermediate(s) from the CA, etc. Point to this file with the `--cert` option
and then also to the key with `--key`. Finally, use `--ssl-only` as needed.
### Requirements
### Additional websockify features
Unless you are using a VNC server with support for WebSockets
connections (only my [fork of libvncserver](http://github.com/kanaka/libvncserver)
currently), you need to use a WebSockets to TCP socket proxy. There is
a python proxy included ('wsproxy'). One advantage of using the proxy
is that it has builtin support for SSL/TLS encryption (i.e. "wss://").
These are not necessary for the basic operation.
There a few reasons why a proxy is required:
* Daemonizing: When the `-D` option is specified, websockify runs
in the background as a daemon process.
1. WebSockets is not a pure socket protocol. There is an initial HTTP
like handshake to allow easy hand-off by web servers and allow
some origin policy exchange. Also, each WebSockets frame begins
with 0 ('\x00') and ends with 255 ('\xff').
* SSL (the wss:// WebSockets URI): This is detected automatically by
websockify by sniffing the first byte sent from the client and then
wrapping the socket if the data starts with '\x16' or '\x80'
(indicating SSL).
2. Javascript itself does not have the ability to handle pure byte
arrays. The python proxy encodes the data as base64 so that the
Javascript client can decode the data as an integer array.
* Session recording: This feature that allows recording of the traffic
sent and received from the client to a file using the `--record`
option.
* Mini-webserver: websockify can detect and respond to normal web
requests on the same port as the WebSockets proxy. This functionality
is activated with the `--web DIR` option where DIR is the root of the
web directory to serve.
* Wrap a program: see the "Wrap a Program" section below.
* Log files: websockify can save all logging information in a file.
This functionality is activated with the `--log-file FILE` option
where FILE is the file where the logs should be saved.
* Authentication plugins: websockify can demand authentication for
websocket connections and, if you use `--web-auth`, also for normal
web requests. This functionality is activated with the
`--auth-plugin CLASS` and `--auth-source ARG` options, where CLASS is
usually one from auth_plugins.py and ARG is the plugin's configuration.
* Token plugins: a single instance of websockify can connect clients to
multiple different pre-configured targets, depending on the token sent
by the client using the `token` URL parameter, or the hostname used to
reach websockify, if you use `--host-token`. This functionality is
activated with the `--token-plugin CLASS` and `--token-source ARG`
options, where CLASS is usually one from token_plugins.py and ARG is
the plugin's configuration.
### Other implementations of websockify
The primary implementation of websockify is in python. There are
several alternate implementations in other languages available in
our sister repositories [websockify-js](https://github.com/novnc/websockify-js)
(JavaScript/Node.js) and [websockify-other](https://github.com/novnc/websockify-other)
(C, Clojure, Ruby).
In addition there are several other external projects that implement
the websockify "protocol". See the alternate implementation [Feature
Matrix](https://github.com/novnc/websockify/wiki/Feature_Matrix) for
more information.
### Quick Start
### Wrap a Program
* Use the launch script to start a mini-webserver and the WebSockets
proxy. The `--vnc` option is used to specify the location of
a running VNC server:
In addition to proxying from a source address to a target address
(which may be on a different system), websockify has the ability to
launch a program on the local system and proxy WebSockets traffic to
a normal TCP port owned/bound by the program.
`./utils/launch.sh --vnc localhost:5901`
This is accomplished by the LD_PRELOAD library (`rebind.so`)
which intercepts bind() system calls by the program. The specified
port is moved to a new localhost/loopback free high port. websockify
then proxies WebSockets traffic directed to the original port to the
new (moved) port of the program.
* Point your browser to the cut-and-paste URL that is output by the
launch script. Enter a password if the VNC server has one
configured. Hit the Connect button and enjoy!
The program wrap mode is invoked by replacing the target with `--`
followed by the program command line to wrap.
`./run 2023 -- PROGRAM ARGS`
The `--wrap-mode` option can be used to indicate what action to take
when the wrapped program exits or daemonizes.
Here is an example of using websockify to wrap the vncserver command
(which backgrounds itself) for use with
[noVNC](https://github.com/novnc/noVNC):
`./run 5901 --wrap-mode=ignore -- vncserver -geometry 1024x768 :1`
Here is an example of wrapping telnetd (from krb5-telnetd). telnetd
exits after the connection closes so the wrap mode is set to respawn
the command:
`sudo ./run 2023 --wrap-mode=respawn -- telnetd -debug 2023`
The `wstelnet.html` page in the [websockify-js](https://github.com/novnc/websockify-js)
project demonstrates a simple WebSockets based telnet client (use
'localhost' and '2023' for the host and port respectively).
### Advanced usage
### Installing websockify
* To encrypt the traffic using the WebSocket 'wss://' URI scheme you
need to generate a certificate for the proxy to load. By default the
proxy loads a certificate file name `self.pem` but the `--cert=CERT`
option can override the file name. You can generate a self-signed
certificate using openssl. When asked for the common name, use the
hostname of the server where the proxy will be running:
Download one of the releases or the latest development version, extract
it and run `python3 setup.py install` as root in the directory where you
extracted the files. Normally, this will also install numpy for better
performance, if you don't have it installed already. However, numpy is
optional. If you don't want to install numpy or if you can't compile it,
you can edit setup.py and remove the `install_requires=['numpy'],` line
before running `python3 setup.py install`.
`openssl req -new -x509 -days 365 -nodes -out self.pem -keyout self.pem`
* `tightvnc` provide a nice startup script that can be used to run
a separate X desktop that is served by VNC. To install and run the
server under Ubuntu you would do something like this:
`sudo apt-get install tightvncserver`
`vncserver :1`
The VNC server will run in the background. The port that it runs
on is the display number + 5900 (i.e. 5901 in the case above).
* `x11vnc` can be used to share your current X desktop. Note that if
you run noVNC on the X desktop you are connecting to via VNC you
will get a neat hall of mirrors effect, but the the client and
server will fight over the mouse.
`sudo apt-get install x11vnc`
`x11vnc -forever -display :0`
Without the `-forever` option, x11vnc will exit after the first
disconnect. The `-display` option indicates the exiting X display to
share. The port that it runs on is the display number + 5900 (i.e.
5900 in the case above).
* To run the python proxy directly without using launch script (to
pass additional options for example):
`./utils/wsproxy.py -f source_port target_addr:target_port`
`./utils/wsproxy.py -f 8787 localhost:5901`
* To run the mini python web server without the launch script:
`./utils/web.py PORT`
`./utils/web.py 8080`
* Point your web browser at http://localhost:8080/vnc.html
(or whatever port you used above to run the web server). Specify the
host and port where the proxy is running and the password that the
vnc server is using (if any). Hit the Connect button.
Afterwards, websockify should be available in your path. Run
`websockify --help` to confirm it's installed correctly.
### Browser Support
### Running with Docker/Podman
You can also run websockify using Docker, Podman, Singularity, udocker or
your favourite container runtime that support OCI container images.
In the following table Jaunty is Ubuntu 9.04 and WinXP is Windows XP.
The entrypoint of the image is the `run` command.
#### Linux (Ubuntu 9.04)
To build the image:
```
./docker/build.sh
```
<table>
<tr>
<th>OS</th> <th>Browser</th>
<th>Status</th>
<th>Notes</th>
</tr> <tr>
<td>Jaunty</td> <td>Chrome 5.0.375.29</td>
<td>Excellent</td>
<td>Very fast. Native WebSockets.</td>
</tr> <tr>
<td>Jaunty</td> <td>Firefox 3.5</td>
<td>Good</td>
<td>Large full-color images are somewhat slow from web-socket-js overhead.</td>
</tr> <tr>
<td>Jaunty</td> <td>Firefox 3.0.17</td>
<td>Fair</td>
<td>Works fine but is slow.</td>
</tr> <tr>
<td>Jaunty</td> <td>Opera 10.60</td>
<td>Poor</td>
<td>web-socket-js problems, mouse/keyboard issues. See note 1</td>
</tr> <tr>
<td>Jaunty</td> <td>Arora 0.5</td>
<td>Good</td>
<td>Broken putImageData so large full-color images
are slow. Uses web-socket-js.</td>
</tr> <tr>
<td>Jaunty</td> <td>Konqueror 4.2.2</td>
<td><strong>Broken</strong></td>
<td>web-socket-js never loads</td>
</tr> <tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr> <tr>
<td>WinXP</td> <td>Chrome 5.0.375.99</td>
<td>Excellent</td>
<td>Very fast. Native WebSockets.</td>
</tr> <tr>
<td>WinXP</td> <td>Firefox 3.0.19</td>
<td>Good</td>
<td>Some overhead from web-socket-js.</td>
</tr> <tr>
<td>WinXP</td> <td>Safari 5.0</td>
<td>Fair</td>
<td>Fast. Native WebSockets. Broken 'wss://' (SSL) - weird client header</td>
</tr> <tr>
<td>WinXP</td> <td>IE 6, 7, 8</td>
<td><strong>Non-starter</strong></td>
<td>No basic Canvas support. Javascript painfully slow.</td>
</tr>
</table>
Once built you can just launch it with the same
arguments you would give to the `run` command and taking care of
assigning the port mappings:
```
docker run -it --rm -p <port>:<container_port> novnc/websockify <container_port> <run_arguments>
```
For example to forward traffic from local port 7000 to 10.1.1.1:5902
you can use:
```
docker run -it --rm -p 7000:80 novnc/websockify 80 10.1.1.1:5902
```
* Note 1: Opera interacts poorly with web-socket-js. After two
disconnects the browser tab or Flash often hang. Although Javascript
is faster than Firefox 3.5, the high variability of web-socket-js
performance results in overall performance being lower. Middle mouse
clicks and keyboard events need some work to work properly under
Opera. Also, Opera does not have support for setting the cursor
style url to a data URI scheme, so cursor pseudo-encoding is
disabled.
### Integration
The client is designed to be easily integrated with existing web
structure and style.
At a minimum you must include the `vnc.js` and `default_controls.js`
scripts and call DefaultControls.load(). For example:
<head>
<script src='include/vnc.js'></script>
<script src="include/default_controls.js"></script>
</head>
<body>
<div id='vnc'>Loading</div>
<script>
window.onload = function () {
DefaultControls.load('vnc');
}
</script>
</body>
See `vnc.html` and `vnc_auto.html` for examples. The file
`include/plain.css` has a list of stylable elements.
The `vnc.js` also includes other scripts within the `include`
sub-directory. The `VNC_uri_prefix` variable can be use override the
URL path to the `include` sub-directory.
### Troubleshooting
You will need console logging support in the browser. Recent Chrome
and Opera versions have built in support. Firefox has a nice extension
called "firebug" that gives console logging support.
First, load the noVNC page with `logging=debug` added to the query string.
For example `vnc.html?logging=debug`.
Then, activate the console logger in your browser. With Chrome it can
be activate using Ctrl+Shift+J and then switching to the "Console"
tab. With firefox+firebug, it can be activated using Ctrl+F12.
Now reproduce the problem. The console log output will give more
information about what is going wrong and where in the code the
problem is located.
If you file a issue/bug, it is very helpful for me to have the last
page of console output leading up the problem in the issue report.
Other helpful issue/bug information: browser version, OS version,
noVNC git version, and VNC server name/version.
If you need to include files, like for example for the `--web` or `--cert`
options you can just mount the required files in the `/data` volume and then
you can reference them in the usual way:
```
docker run -it --rm -p 443:443 -v websockify-data:/data novnc/websockify --cert /data/self.pem --web /data/noVNC :443 --token-plugin TokenRedis --token-source myredis.local:6379 --ssl-only --ssl-version tlsv1_2
```
+61
View File
@@ -0,0 +1,61 @@
Running Websockify as a Windows service
=======================================
Installation and configuration
------------------------------
Download the following software:
* Python, from https://www.python.org/downloads/windows/
* SrvAny, from http://simpleauto.byethost8.com/Zip/SrvAny.zip
Note that there is [a modern alternative for SrvAny](https://github.com/rwmjones/rhsrvany),
but that project does not provide binaries.
Install Python for all users, not just the current one. Extract Websockify
into a directory, e.g. `C:\Program Files\websockify`, so that e.g.
`README.md` ends up there. Extract the `SrvAny.zip` archive, copy the
`WIN7\SrvAny.exe` file into `C:\Program Files\websockify`.
Then create a batch file, `C:\Program Files\websockify\run.bat`, that runs
Websockify from its directory with the correct options under the correct
Python interpreter:
```
C:
cd "\Program Files\websockify"
"C:\Program Files\Python39\python.exe" -m websockify 5901 127.0.0.1:5900
```
Run it by hand once so that Windows asks you about a firewall exception.
After confirming the exception, press `Ctrl+C` to terminate the script.
Then create a Windows service for Websockify (use an Administrator command
prompt for that). For paths with spaces, like in this example, double-escaping
is needed: once for `cmd.exe` and once for `SrvAny.exe`.
```
C:
cd "\Program Files\websockify"
SrvAny.exe -install Websockify 10s \\\"C:\Program Files\websockify\run.bat\\\"
```
In the Windows Control Panel, under Services, a new "Websockify" service will
appear. In its properties dialog, you can change the startup type, e.g. make
it start automatically at boot. Or, you can start the service manually.
Uninstallation
--------------
If you want to remove the service, first set its startup type to Manual, then
reboot the PC. Then run this command using the Administrator command prompt:
```
C:
cd "\Program Files\websockify"
SrvAny.exe -remove Websockify
```
After that, you will be able to remove the `C:\Program Files\websockify`
directory completely.
+16
View File
@@ -0,0 +1,16 @@
FROM python
COPY websockify-*.tar.gz /
RUN python3 -m pip install websockify-*.tar.gz
RUN rm -rf /websockify-* /root/.cache
VOLUME /data
EXPOSE 80
EXPOSE 443
WORKDIR /opt/websockify
ENTRYPOINT ["/usr/local/bin/websockify"]
CMD ["--help"]
+5
View File
@@ -0,0 +1,5 @@
#!/usr/bin/env sh
set -e -x
cd "$(dirname "$0")"
(cd .. && python3 setup.py sdist --dist-dir docker/)
docker build -t novnc/websockify .
-621
View File
@@ -1,621 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
-51
View File
@@ -1,51 +0,0 @@
Short Term:
- Proper Javascript namespacing for Canvas and RFB (using function for
true local variables and functions).
- Timing delta between frames in proxy record log, for playback
support (for demo and test).
- Playback/demo on website.
- Test on IE 9 preview 3.
- Fix cursor URI detection in Arora:
- allows data URI, but doesn't actually work
Medium Term:
- Viewport support
- Status bar menu/buttons:
- Explanatory hover text over buttons
- Configuration menu:
- Tunable: speed vs. bandwidth selection
- Tunable: CPU use versus latency.
- shared mode
- Scaling
- Keyboard menu:
- Ctrl Lock, Alt Lock, SysRq Lock
- Highlight menu icon when keys are locked
- Clipboard button -> popup:
- text, clear and send buttons
Longer Term:
- Implement UI option for VNC shared mode.
- Get web-socket-js RFC2817 proxying working again.
- Implement tight and ZRLE encoding
- Support for Spice protocol.
- Consider RDP protocol.
- Consider NX protocol.
+114
View File
@@ -0,0 +1,114 @@
This data is raw copy from the latency tester set to send a frame with
a little over 2000 KB of data every 10ms.
The number of packets sent and received is just a visual counter and
is just the total when I chose to stop the test (around 3000 or so
packets).
The latency measure are from the point the packet was sent to when it
was received back again in milliseconds. One notable data point
missing from this is how long it actually took for the client to send
3000 packets because sending large packets can put load on the browser
and it may be a lot longer than 10ms before the timer event to
send the next packet fires. So even with low latency numbers, the
actual send rate may be fairly low because sending the WebSockets
frames is impacting the performance of the browser in general.
------------------------------------------------------------
Native WebSockets implementations, 2000 byte payload, 10ms delay
Chrome 8.0.552 - native WebSockets
Packets sent: 2998
Packets Received: 2998
Average Latency: 1.84
40 Frame Running Average Latency: 1.90
Minimum Latency: 1.00
Maximum Latency: 10.00
firefox 4.0b9 - WebSockets enabled
Packets sent: 3011
Packets Received: 3011
Average Latency: 6.45
40 Frame Running Average Latency: 6.08
Minimum Latency: 5.00
Maximum Latency: 119.00
Opera 11 - WebSockets enabled
Packets sent: 3065
Packets Received: 3064
Average Latency: 9.56
40 Frame Running Average Latency: 8.15
Minimum Latency: 4.00
Maximum Latency: 53.00
------------------------------------------------------------
New web-socket-js (20f837425d4), 2000 byte payload, 10ms delay
firefox 4.0b9 - no WebSockets
Packets sent: 3088
Packets Received: 3087
Average Latency: 16.71
40 Frame Running Average Latency: 16.80
Minimum Latency: 7.00
Maximum Latency: 75.00
- First 1000 sent in 13 seconds
- Second 1000 sent in 12 seconds
- Third 1000 sent in 12 seconds
firefox 3.6.10 - no WebSockets
Packets sent: 3100
Packets Received: 3099
Average Latency: 17.32
40 Frame Running Average Latency: 16.73
Minimum Latency: 6.00
Maximum Latency: 72.00
Opera 11 - no WebSockets
Packets sent: 3007
Packets Received: 3007
Average Latency: 465.91
40 Frame Running Average Latency: 147.95
Minimum Latency: 12.00
Maximum Latency: 9143.00
- average starts at around 28ms
- time for each 500 packets: 13s, 16s, 25s, 37s, 50s, 72s
- also start seeing sent, receive lags around 1200 packets
---------------------------------------------------------------
Old web-socket-js (9e7663771), 2000 byte payload, 10ms delay
firefox 4.0b9 - no WebSockets
Packets sent: 3024
Packets Received: 3020
Average Latency: 80.59
40 Frame Running Average Latency: 60.15
Minimum Latency: 10.00
Maximm Latency: 348.00
firefox 3.6.10 - no WebSockets
Packets sent: 2777
Packets Received: 2775
Average Latency: 34.89
40 Frame Running Average Latency: 24.50
Minimum Latency: 10.00
Maximum Latency: 208.00
Opera 11 - no Websockets
Packets sent: 3012
Packets Received: 3011
Average Latency: 380.87
40 Frame Running Average Latency: 341.90
Minimum Latency: 28.00
Maximum Latency: 2175.00
- average starts at around 290ms
- time for each 1000 packets: 23s, 38s, 65s
-66
View File
@@ -1,66 +0,0 @@
New tight PNG protocol:
http://wiki.qemu.org/VNC_Tight_PNG
http://xf.iksaif.net/blog/index.php?post/2010/06/14/QEMU:-Tight-PNG-and-some-profiling
RFB protocol and extensions:
http://tigervnc.org/cgi-bin/rfbproto
Canvas Browser Compatibility:
http://philip.html5.org/tests/canvas/suite/tests/results.html
WebSockets API standard:
http://www.whatwg.org/specs/web-apps/current-work/complete.html#websocket
http://dev.w3.org/html5/websockets/
http://www.ietf.org/id/draft-ietf-hybi-thewebsocketprotocol-00.txt
Browser Keyboard Events detailed:
http://unixpapa.com/js/key.html
ActionScript (Flash) WebSocket implementation:
http://github.com/gimite/web-socket-js
ActionScript (Flash) crypto/TLS library:
http://code.google.com/p/as3crypto
http://github.com/lyokato/as3crypto_patched
TLS Protocol:
http://en.wikipedia.org/wiki/Transport_Layer_Security
Generate self-signed certificate:
http://docs.python.org/dev/library/ssl.html#certificates
Cursor appearance/style (for Cursor pseudo-encoding):
http://en.wikipedia.org/wiki/ICO_(file_format)
http://www.daubnet.com/en/file-format-cur
https://developer.mozilla.org/en/Using_URL_values_for_the_cursor_property
Related projects:
guacamole: http://guacamole.sourceforge.net/
- Web client, but Java servlet does pre-processing
jsvnc: http://code.google.com/p/jsvnc/
- No releases
webvnc: http://code.google.com/p/webvnc/
- Jetty web server gateway, no updates since April 2008.
RealVNC Java applet: http://www.realvnc.com/support/javavncviewer.html
- Java applet
Flashlight-VNC: http://www.wizhelp.com/flashlight-vnc/
- Adobe Flash implementation
FVNC: http://osflash.org/fvnc
- Adbove Flash implementation
CanVNC: http://canvnc.sourceforge.net/
- HTML client with REST to VNC python proxy. Mostly vapor.
+5 -43
View File
@@ -1,44 +1,6 @@
Some implementation notes:
Building release tarball:
- not really necessary since tagged revision can be downloaded
from github as tarballs
There is an included flash object (web-socket-js) that is used to
emulate websocket support on browsers without websocket support
(currently only Chrome has WebSocket support).
The performance on Chrome is great. It only takes about 150ms on my
system to render a complete 800x600 hextile frame. Most updates are
partial or use copyrect which is much faster.
When using the flash websocket emulator, packets event aren't always
delivered in order. This may be a bug in the way I'm using the
FABridge interface. Or a bug in FABridge itself, or just a browser
event delivery issue. Anyways, to get around this problem, when the
flash emulator is being used, the client issues the WebSocket GET
request with the "seq_num" variable. This switches on in-band sequence
numbering of the packets in the proxy, and the client has a queue of
out-of-order packets (20 deep currently) that it uses to re-order.
Gross!
The performance on firefox 3.5 is usable. It takes 2.3 seconds to
render a 800x600 hextile frame on my system (the initial connect).
Once the initial first update is done though, it's quite usable (as
above, most updates are partial or copyrect). I haven't tested firefox
3.7 yet, it might be a lot faster.
Opera sucks big time. The flash websocket emulator fails to deliver as
many as 40% of packet events when used on Opera. It may or not be
Opera's fault, but something goes badly wrong at the FABridge
boundary.
Javascript doesn't have a bytearray type, so what you get out of
a WebSocket object is just Javascript strings. I believe that
Javascript has UTF-16 unicode strings and anything sent through the
WebSocket gets converted to UTF-8 and vice-versa. So, one additional
(and necessary) function of the proxy is base64 encoding/decoding what
is sent to/from the browser. Another option that I want to explore is
UTF-8 encoding in the proxy.
Building web-socket-js emulator:
cd include/web-socket-js/flash-src
mxmlc -static-link-runtime-shared-libraries WebSocketMain.as
git archive --format=tar --prefix=websockify-${WVER}/ v${WVER} > websockify-${WVER}.tar
gzip websockify-${WVER}.tar
-67
View File
@@ -1,67 +0,0 @@
Description of the WebSockets to TCP Proxy
At the most basic level, the proxy just translates WebSockets traffic
to normal socket traffic. The proxy accepts the WebSockets header,
parses it, and then begins forwarding traffic between the client and
the target in both directions. At a minimum the proxy needs to base64
encode traffic destined for the client and decode it coming from the
client. Also, WebSockets traffic starts with '\0' (0) and ends with
'\xff' (255) so that needs to be added/stripped by the proxy. There
is a little bit of buffering you need to do in case the data from the
client isn't a full WebSockets frame (i.e. doesn't end in 255).
Other proxy features (that aren't necessary for the basic operation):
SSL (the wss:// WebSockets URI):
This is detected automatically by the proxy by sniffing the first byte
of the client's connection and then wrapping the socket if the data
starts with '\x16' (indicating SSL).
Sequence Numbering:
When the client doesn't have native WebSockets support in the browser
(currently only Chrome and Safari 5), a flash emulator fallback is
used. Unfortunately, when this is used, frame ordering is not 100%,
so the GET URI in the initial handshake has "seq_num=1". This tells
the proxy to add sequence numbers to every WebSockets frame so that
the browser can reorder them.
UTF-8 encoding:
In addition to the base64 encoding of the data, the proxy also
supports UTF-8 encoding of the data (the native WebSockets encoding).
However, in order to not burden the browser too much, the encoding
doesn't use the full UTF-8 value space, but only uses the first 256
values. This actually makes UTF-8 encoding slightly less space
efficient than base64. Also, flash cannot handle byte arrays with 0's
in them properly, so the values are actually 1-256 (rather than 0-255)
and the browser does modulus 256 on the data. For these two reasons,
base64 is the default and is indicated in the GET string by
"base64=1".
Flash security policy:
The proxy detects flash security policy requests (again by sniffing
the first packet) and answers with an appropriate flash security
policy response (and then closes the port). This means no separate
flash security policy server is needed for supporting the flash
WebSockets fallback emulator.
Daemonizing:
The proxy also supports daemonizing (when the -f option is not
specified).
Record:
Finally, there is a debug feature that allows recording of the traffic
sent and received from the client to a file (the --record option).
+10
View File
@@ -0,0 +1,10 @@
- Update setup.py and CHANGES.txt and commit
- Create version tag and tarball from tag
WVER=0.1.0
git tag v${WVER}
git push origin master
git push origin v${WVER}
- Create the source distribution
python3 setup.py sdist
- Upload the source distribution
python3 -m twine upload dist/websockify-${WVER}.tar.gz
-147
View File
@@ -1,147 +0,0 @@
5.1.1 ProtocolVersion: 12, 12 bytes
- Sent by server, max supported
12 ascii - "RFB 003.008\n"
- Response by client, version to use
12 ascii - "RFB 003.003\n"
5.1.2 Authentication: >=4, [16, 4] bytes
- Sent by server
CARD32 - authentication-scheme
0 - connection failed
CARD32 - length
length - reason
1 - no authentication
2 - VNC authentication
16 CARD8 - challenge (random bytes)
- Response by client (if VNC authentication)
16 CARD8 - client encrypts the challenge with DES, using user
password as key, sends resulting 16 byte response
- Response by server (if VNC authentication)
CARD32 - 0 - OK
1 - failed
2 - too-many
5.1.3 ClientInitialisation: 1 byte
- Sent by client
CARD8 - shared-flag, 0 exclusive, non-zero shared
5.1.4 ServerInitialisation: >=24 bytes
- Sent by server
CARD16 - framebuffer-width
CARD16 - framebuffer-height
16 byte PIXEL_FORMAT - server-pixel-format
CARD8 - bits-per-pixel
CARD8 - depth
CARD8 - big-endian-flag, non-zero is big endian
CARD8 - true-color-flag, non-zero then next 6 apply
CARD16 - red-max
CARD16 - green-max
CARD16 - blue-max
CARD8 - red-shift
CARD8 - green-shift
CARD8 - blue-shift
3 bytes - padding
CARD32 - name-length
CARD8[length] - name-string
Client to Server Messages:
5.2.1 SetPixelFormat: 20 bytes
CARD8: 0 - message-type
...
5.2.2 FixColourMapEntries: >=6 bytes
CARD8: 1 - message-type
...
5.2.3 SetEncodings: >=8 bytes
CARD8: 2 - message-type
CARD8 - padding
CARD16 - numer-of-encodings
CARD32 - encoding-type in preference order
0 - raw
1 - copy-rectangle
2 - RRE
4 - CoRRE
5 - hextile
5.2.4 FramebufferUpdateRequest (10 bytes)
CARD8: 3 - message-type
CARD8 - incremental (0 for full-update, non-zero for incremental)
CARD16 - x-position
CARD16 - y-position
CARD16 - width
CARD16 - height
5.2.5 KeyEvent: 8 bytes
CARD8: 4 - message-type
CARD8 - down-flag
2 bytes - padding
CARD32 - key (X-Windows keysym values)
5.2.6 PointerEvent: 6 bytes
CARD8: 5 - message-type
CARD8 - button-mask
CARD16 - x-position
CARD16 - y-position
5.2.7 ClientCutText: >=9 bytes
CARD8: 6 - message-type
...
Server to Client Messages:
5.3.1 FramebufferUpdate
CARD8: 0 - message-type
1 byte - padding
CARD16 - number-of-rectangles
CARD16 - x-position
CARD16 - y-position
CARD16 - width
CARD16 - height
CARD16 - encoding-type:
0 - raw
1 - copy rectangle
2 - RRE
4 - CoRRE
5 - hextile
raw:
- width x height pixel values
copy rectangle:
CARD16 - src-x-position
CARD16 - src-y-position
RRE:
CARD32 - N number-of-subrectangles
Nxd bytes - background-pixel-value (d bits-per-pixel)
...
5.3.2 SetColourMapEntries (no support)
CARD8: 1 - message-type
...
5.3.3 Bell
CARD8: 2 - message-type
5.3.4 ServerCutText
CARD8: 3 - message-type
Binary file not shown.
Binary file not shown.
Binary file not shown.
+110
View File
@@ -0,0 +1,110 @@
.TH websockify 1 "June 7, 2012" "version 0.3" "USER COMMANDS"
.SH NAME
websockify - WebSockets to TCP socket bridge
.SH SYNOPSIS
websockify [options] [source_addr:]source_port target_addr:target_port
websockify [options] [source_addr:]source_port \-\- WRAP_COMMAND_LINE
.SH OPTIONS
-h, --help show this help message and exit
-v, --verbose verbose messages and per frame traffic
--record=FILE record sessions to FILE.[session_number]
-D, --daemon become a daemon (background process)
--run-once handle a single WebSocket connection and exit
--timeout=TIMEOUT after TIMEOUT seconds exit when not connected
--cert=CERT SSL certificate file
--key=KEY SSL key file (if separate from cert)
--ssl-only disallow non-encrypted connections
--web=DIR run webserver on same port. Serve files from DIR.
--wrap-mode=MODE action to take when the wrapped program exits or
daemonizes: exit (default), ignore, respawn
.SH DESCRIPTION
At the most basic level, websockify just translates WebSockets traffic to normal TCP socket traffic. Websockify accepts the WebSockets handshake, parses it, and then begins forwarding traffic between the client and the target in both directions.
websockify was formerly named wsproxy and was part of the noVNC project.
.SH NOTES
.SS WebSockets binary data
Websockify supports all versions of the WebSockets protocol (Hixie and HyBI). The older Hixie versions of the protocol only support UTF-8 text payloads. In order to transport binary data over UTF-8 an encoding must used to encapsulate the data within UTF-8. Websockify uses base64 to encode all traffic to and from the client. This does not affect the data between websockify and the server.
.SS Encrypted WebSocket connections (wss://)
To encrypt the traffic using the WebSocket 'wss://' URI scheme you need to generate a certificate for websockify to load. By default websockify loads a certificate file name self.pem but the --cert=CERT option can override the file name. You can generate a self-signed certificate using openssl. When asked for the common name, use the hostname of the server where the proxy will be running:
openssl req -new -x509 -days 365 -nodes -out self.pem -keyout self.pem
.SS Additional websockify features
These are not necessary for the basic operation.
.IP *
Daemonizing: When the -D option is specified, websockify runs in the background as a daemon process.
.IP *
SSL (the wss:// WebSockets URI): This is detected automatically by websockify by sniffing the first byte sent from the client and then wrapping the socket if the data starts with '\\x16' or '\\x80' (indicating SSL).
.IP *
Session recording: This feature that allows recording of the traffic sent and received from the client to a file using the --record option.
.IP *
Mini-webserver: websockify can detect and respond to normal web requests on the same port as the WebSockets proxy. This functionality is activate with the --web DIR option where DIR is the root of the web directory to serve.
.IP *
Wrap a program: see the "Wrap a Program" section below.
.SS Wrap a Program
In addition to proxying from a source address to a target address (which may be on a different system), websockify has the ability to launch a program on the local system and proxy WebSockets traffic to a normal TCP port owned/bound by the program.
The is accomplished with a small LD_PRELOAD library (rebind.so) which intercepts bind() system calls by the program. The specified port is moved to a new localhost/loopback free high port. websockify then proxies WebSockets traffic directed to the original port to the new (moved) port of the program.
The program wrap mode is invoked by replacing the target with -- followed by the program command line to wrap.
`./websockify 2023 -- PROGRAM ARGS`
The --wrap-mode option can be used to indicate what action to take when the wrapped program exits or daemonizes.
Here is an example of using websockify to wrap the vncserver command (which backgrounds itself) for use with noVNC:
`./websockify 5901 --wrap-mode=ignore -- vncserver -geometry 1024x768 :1`
Here is an example of wrapping telnetd (from krb5-telnetd). telnetd exits after the connection closes so the wrap mode is set to respawn the command:
`sudo ./websockify 2023 --wrap-mode=respawn -- telnetd -debug 2023`
The wstelnet.html page demonstrates a simple WebSockets based telnet client.
.SS Use client certificate verification
This feature requires Python 2.7.9 or newer or Python 3.4 or newer.
The --verify-client option makes the server ask the client for a SSL certificate. Presenting a valid (not expired and trusted by any supplied certificate authority) certificate is required for the client connection. With -auth-plugin=ClientCertCNAuth, the client certificate can be checked against a list of authorised certificate users. Non-encrypted connection attempts always fail during authentication.
Here is an example of a vncsevrer with password-less, certificate-driven authentication:
`./websockify 5901 --cert=fullchain.pem --key=privkey.pem --ssl-only --verify-client --cafile=ca-certificates.crt --auth-plugin=ClientCertCNAuth --auth-source='jane@example.com Joe User9824510' --web=noVNC/ --wrap-mode=ignore -- vncserver :1 -geometry 1024x768 -SecurityTypes=None`
The --auth-source option takes a white-space separated list of common names. Depending on your clients certificates they can be verified email addresses, user-names or any other string used for identification.
The --cafile option selects a file containing concatenated certificates of authorities trusted for validating clients. If this option is omitted, system default list of CAs is used. Upon connect, the client should supply the whole certificate chain. If your clients are known not to send intermediate certificates, they can be appended to the ca-file as well.
Note: Most browsers ask the user to select a certificate only while connecting via HTTPS, not WebSockets. Connecting directly to the SSL secured WebSocket may cause the browser to abort the connection. If you want to connect via noVNC, the --web option should point to a copy of noVNC, so it is loaded from the same host.
.SH AUTHOR
Joel Martin (github@martintribe.org)
.SH SEE ALSO
https://github.com/novnc/websockify/
https://github.com/novnc/websockify/wiki/
-75
View File
@@ -1,75 +0,0 @@
This software is covered under the following copyright:
/*
* Copyright (c) 2007 Henri Torgemane
* All Rights Reserved.
*
* BigInteger, RSA, Random and ARC4 are derivative works of the jsbn library
* (http://www-cs-students.stanford.edu/~tjw/jsbn/)
* The jsbn library is Copyright (c) 2003-2005 Tom Wu (tjw@cs.Stanford.EDU)
*
* MD5, SHA1, and SHA256 are derivative works (http://pajhome.org.uk/crypt/md5/)
* Those are Copyright (c) 1998-2002 Paul Johnston & Contributors (paj@pajhome.org.uk)
*
* SHA256 is a derivative work of jsSHA2 (http://anmar.eu.org/projects/jssha2/)
* jsSHA2 is Copyright (c) 2003-2004 Angel Marin (anmar@gmx.net)
*
* AESKey is a derivative work of aestable.c (http://www.geocities.com/malbrain/aestable_c.html)
* aestable.c is Copyright (c) Karl Malbrain (malbrain@yahoo.com)
*
* BlowFishKey, DESKey and TripeDESKey are derivative works of the Bouncy Castle Crypto Package (http://www.bouncycastle.org)
* Those are Copyright (c) 2000-2004 The Legion Of The Bouncy Castle
*
* Base64 is copyright (c) 2006 Steve Webster (http://dynamicflash.com/goodies/base64)
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer. Redistributions in binary form must
* reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* Neither the name of the author nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
Address all questions regarding this license to:
Henri Torgemane
henri_torgemane@yahoo.com
Additionally, the MD5 algorithm is covered by the following notice:
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved.
*
* License to copy and use this software is granted provided that it
* is identified as the "RSA Data Security, Inc. MD5 Message-Digest
* Algorithm" in all material mentioning or referencing this software
* or this function.
*
* License is also granted to make and use derivative works provided
* that such works are identified as "derived from the RSA Data
* Security, Inc. MD5 Message-Digest Algorithm" in all material
* mentioning or referencing the derived work.
*
* RSA Data Security, Inc. makes no representations concerning either
* the merchantability of this software or the suitability of this
* software for any particular purpose. It is provided "as is"
* without express or implied warranty of any kind.
*
* These notices must be retained in any copies of any part of this
* documentation and/or software.
*/
-13
View File
@@ -1,13 +0,0 @@
= DESCRIPTION
as3crypto 1.3 has some bugs, at r28(latest version of original svn-repository),
many of them are fixed, but there are another bugs around a new ASN1 parser.
so I copied some features from r28 to 1.3
version, and fixed them to be built without error.
and added build-swc.xml
= LICENSE
See LICENCE.txt,
-15
View File
@@ -1,15 +0,0 @@
require 'rubygems'
require 'airake'
ENV["AIRAKE_ROOT"] = File.dirname(__FILE__)
ENV["AIRAKE_ENV"] = "development"
# Aliases
task :test => [ "air:test" ] do; end
task :compile => [ "air:compile" ] do; end
task :package => [ "air:package" ] do; end
task :certificate => [ "air:certificate" ] do; end
task :adl => [ "air:adl" ] do; end
task :docs => [ "air:docs" ] do; end
task :clean => [ "air:clean" ] do; end
task :acompc => [ "air:acompc" ] do; end
-21
View File
@@ -1,21 +0,0 @@
---
mxml_path: src/As3crypto.mxml
appxml_path: src/As3crypto-app.xml
src_dirs: [ 'src' ]
lib_dir: lib
air_path: bin/As3crypto.air
swf_path: bin/As3crypto.swf
assets: src/assets
certificate: cert.pfx
development:
debug: true
test:
swf_path: bin/Test.swf
mxml_path: test/Test.mxml
appxml_path: test/Test-app.xml
src_dirs: [ 'src', 'test' ]
debug: true
Binary file not shown.
-109
View File
@@ -1,109 +0,0 @@
<!--
To build as3crypto.swc, use
compc -load-config=build-swc.xml
If you need Flash Player 9 support, change the path below to something more
appropriate for your SDK and/or Player version
-->
<flex-config>
<benchmark>true</benchmark>
<compiler>
<external-library-path>
<path-element>${flexlib}/libs/player/10.0/playerglobal.swc</path-element>
</external-library-path>
<source-path>
<path-element>./src</path-element>
</source-path>
</compiler>
<include-classes>
<class>com.hurlant.crypto.Crypto</class>
<class>com.hurlant.crypto.cert.MozillaRootCertificates</class>
<class>com.hurlant.crypto.cert.X509Certificate</class>
<class>com.hurlant.crypto.cert.X509CertificateCollection</class>
<class>com.hurlant.crypto.hash.HMAC</class>
<class>com.hurlant.crypto.hash.IHMAC</class>
<class>com.hurlant.crypto.hash.IHash</class>
<class>com.hurlant.crypto.hash.MAC</class>
<class>com.hurlant.crypto.hash.MD2</class>
<class>com.hurlant.crypto.hash.MD5</class>
<class>com.hurlant.crypto.hash.SHA1</class>
<class>com.hurlant.crypto.hash.SHA224</class>
<class>com.hurlant.crypto.hash.SHA256</class>
<class>com.hurlant.crypto.hash.SHABase</class>
<class>com.hurlant.crypto.prng.ARC4</class>
<class>com.hurlant.crypto.prng.IPRNG</class>
<class>com.hurlant.crypto.prng.Random</class>
<class>com.hurlant.crypto.prng.TLSPRF</class>
<class>com.hurlant.crypto.rsa.RSAKey</class>
<class>com.hurlant.crypto.symmetric.AESKey</class>
<class>com.hurlant.crypto.symmetric.BlowFishKey</class>
<class>com.hurlant.crypto.symmetric.CBCMode</class>
<class>com.hurlant.crypto.symmetric.CFB8Mode</class>
<class>com.hurlant.crypto.symmetric.CFBMode</class>
<class>com.hurlant.crypto.symmetric.CTRMode</class>
<class>com.hurlant.crypto.symmetric.DESKey</class>
<class>com.hurlant.crypto.symmetric.ECBMode</class>
<class>com.hurlant.crypto.symmetric.ICipher</class>
<class>com.hurlant.crypto.symmetric.IMode</class>
<class>com.hurlant.crypto.symmetric.IPad</class>
<class>com.hurlant.crypto.symmetric.IStreamCipher</class>
<class>com.hurlant.crypto.symmetric.ISymmetricKey</class>
<class>com.hurlant.crypto.symmetric.IVMode</class>
<class>com.hurlant.crypto.symmetric.NullPad</class>
<class>com.hurlant.crypto.symmetric.OFBMode</class>
<class>com.hurlant.crypto.symmetric.PKCS5</class>
<class>com.hurlant.crypto.symmetric.SimpleIVMode</class>
<class>com.hurlant.crypto.symmetric.TLSPad</class>
<class>com.hurlant.crypto.symmetric.SSLPad</class>
<class>com.hurlant.crypto.symmetric.TripleDESKey</class>
<class>com.hurlant.crypto.symmetric.XTeaKey</class>
<class>com.hurlant.crypto.tls.BulkCiphers</class>
<class>com.hurlant.crypto.tls.CipherSuites</class>
<class>com.hurlant.crypto.tls.KeyExchanges</class>
<class>com.hurlant.crypto.tls.MACs</class>
<class>com.hurlant.crypto.tls.TLSConfig</class>
<class>com.hurlant.crypto.tls.IConnectionState</class>
<class>com.hurlant.crypto.tls.TLSConnectionState</class>
<class>com.hurlant.crypto.tls.SSLConnectionState</class>
<class>com.hurlant.crypto.tls.TLSEngine</class>
<class>com.hurlant.crypto.tls.TLSError</class>
<class>com.hurlant.crypto.tls.TLSSocketEvent</class>
<class>com.hurlant.crypto.tls.TLSEvent</class>
<class>com.hurlant.crypto.tls.SSLEvent</class>
<class>com.hurlant.crypto.tls.ISecurityParameters</class>
<class>com.hurlant.crypto.tls.TLSSecurityParameters</class>
<class>com.hurlant.crypto.tls.SSLSecurityParameters</class>
<class>com.hurlant.crypto.tls.TLSSocket</class>
<class>com.hurlant.util.ArrayUtil</class>
<class>com.hurlant.util.Base64</class>
<class>com.hurlant.util.Hex</class>
<class>com.hurlant.util.Memory</class>
<class>com.hurlant.util.der.ByteString</class>
<class>com.hurlant.util.der.DER</class>
<class>com.hurlant.util.der.IAsn1Type</class>
<class>com.hurlant.util.der.Integer</class>
<class>com.hurlant.util.der.OID</class>
<class>com.hurlant.util.der.ObjectIdentifier</class>
<class>com.hurlant.util.der.PEM</class>
<class>com.hurlant.util.der.PrintableString</class>
<class>com.hurlant.util.der.Sequence</class>
<class>com.hurlant.util.der.Set</class>
<class>com.hurlant.util.der.Type</class>
<class>com.hurlant.util.der.UTCTime</class>
<class>com.hurlant.math.BarrettReduction</class>
<class>com.hurlant.math.BigInteger</class>
<class>com.hurlant.math.ClassicReduction</class>
<class>com.hurlant.math.IReduction</class>
<class>com.hurlant.math.MontgomeryReduction</class>
<class>com.hurlant.math.NullReduction</class>
<class>com.hurlant.math.bi_internal</class>
</include-classes>
<metadata>
<creator>Henri Torgemane</creator>
<description>http://crypto.hurlant.com/</description>
<language>EN</language>
<title>AS3 Cryptography Library</title>
</metadata>
<output>bin/as3crypto_patched.swc</output>
</flex-config>
Binary file not shown.
-14
View File
@@ -1,14 +0,0 @@
#!/usr/bin/env ruby
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
begin
require 'rubigen'
rescue LoadError
require 'rubygems'
require 'rubigen'
end
require 'rubigen/scripts/destroy'
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
RubiGen::Base.use_component_sources! [:air, :airake, :test_unit]
RubiGen::Scripts::Destroy.new.run(ARGV)
-14
View File
@@ -1,14 +0,0 @@
#!/usr/bin/env ruby
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
begin
require 'rubigen'
rescue LoadError
require 'rubygems'
require 'rubigen'
end
require 'rubigen/scripts/generate'
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
RubiGen::Base.use_component_sources! [:air, :airake, :test_unit]
RubiGen::Scripts::Generate.new.run(ARGV)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

@@ -1,287 +0,0 @@
/**
* Crypto
*
* An abstraction layer to instanciate our crypto algorithms
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto
{
import com.hurlant.crypto.hash.HMAC;
import com.hurlant.crypto.hash.MAC;
import com.hurlant.crypto.hash.IHash;
import com.hurlant.crypto.hash.MD2;
import com.hurlant.crypto.hash.MD5;
import com.hurlant.crypto.hash.SHA1;
import com.hurlant.crypto.hash.SHA224;
import com.hurlant.crypto.hash.SHA256;
import com.hurlant.crypto.prng.ARC4;
import com.hurlant.crypto.rsa.RSAKey;
import com.hurlant.crypto.symmetric.AESKey;
import com.hurlant.crypto.symmetric.BlowFishKey;
import com.hurlant.crypto.symmetric.CBCMode;
import com.hurlant.crypto.symmetric.CFB8Mode;
import com.hurlant.crypto.symmetric.CFBMode;
import com.hurlant.crypto.symmetric.CTRMode;
import com.hurlant.crypto.symmetric.DESKey;
import com.hurlant.crypto.symmetric.ECBMode;
import com.hurlant.crypto.symmetric.ICipher;
import com.hurlant.crypto.symmetric.IMode;
import com.hurlant.crypto.symmetric.IPad;
import com.hurlant.crypto.symmetric.ISymmetricKey;
import com.hurlant.crypto.symmetric.IVMode;
import com.hurlant.crypto.symmetric.NullPad;
import com.hurlant.crypto.symmetric.OFBMode;
import com.hurlant.crypto.symmetric.PKCS5;
import com.hurlant.crypto.symmetric.SimpleIVMode;
import com.hurlant.crypto.symmetric.TripleDESKey;
import com.hurlant.crypto.symmetric.XTeaKey;
import com.hurlant.util.Base64;
import flash.utils.ByteArray;
/**
* A class to make it easy to use the rest of the framework.
* As a side-effect, using this class will cause most of the framework
* to be linked into your application, which is not always what you want.
*
* If you want to optimize your download size, don't use this class.
* (But feel free to read it to get ideas on how to get the algorithm you want.)
*/
public class Crypto
{
private var b64:Base64; // we don't use it, but we want the swc to include it, so cheap trick.
public function Crypto(){
}
/**
* Things that should work, among others:
* "aes"
* "aes-128-ecb"
* "aes-128-cbc"
* "aes-128-cfb"
* "aes-128-cfb8"
* "aes-128-ofb"
* "aes-192-cfb"
* "aes-256-ofb"
* "blowfish-cbc"
* "des-ecb"
* "xtea"
* "xtea-ecb"
* "xtea-cbc"
* "xtea-cfb"
* "xtea-cfb8"
* "xtea-ofb"
* "rc4"
* "simple-aes-cbc"
*/
public static function getCipher(name:String, key:ByteArray, pad:IPad=null):ICipher {
// split name into an array.
var keys:Array = name.split("-");
switch (keys[0]) {
/**
* "simple" is a special case. It means:
* "If using an IV mode, prepend the IV to the ciphertext"
*/
case "simple":
keys.shift();
name = keys.join("-");
var cipher:ICipher = getCipher(name, key, pad);
if (cipher is IVMode) {
return new SimpleIVMode(cipher as IVMode);
} else {
return cipher;
}
/**
* we support both "aes-128" and "aes128"
* Technically, you could use "aes192-128", but you'd
* only be hurting yourself.
*/
case "aes":
case "aes128":
case "aes192":
case "aes256":
keys.shift();
if (key.length*8==keys[0]) {
// support for "aes-128-..." and such.
keys.shift();
}
return getMode(keys[0], new AESKey(key), pad);
break;
case "bf":
case "blowfish":
keys.shift();
return getMode(keys[0], new BlowFishKey(key), pad);
/**
* des-ede and des-ede3 are both equivalent to des3.
* the choice between 2tdes and 3tdes is made based
* on the length of the key provided.
*/
case "des":
keys.shift();
if (keys[0]!="ede" && keys[0]!="ede3") {
return getMode(keys[0], new DESKey(key), pad);
}
if (keys.length==1) {
keys.push("ecb"); // default mode for 2tdes and 3tdes with openssl enc
}
// fall-through to triple des
case "3des":
case "des3":
keys.shift();
return getMode(keys[0], new TripleDESKey(key), pad);
case "xtea":
keys.shift();
return getMode(keys[0], new XTeaKey(key), pad);
break;
/**
* Technically, you could say "rc4-128" or whatever,
* but really, the length of the key is what counts here.
*/
case "rc4":
keys.shift();
return new ARC4(key);
break;
}
return null;
}
/**
* Returns the size of a key for a given cipher identifier.
*/
public static function getKeySize(name:String):uint {
var keys:Array = name.split("-");
switch (keys[0]) {
case "simple":
keys.shift();
return getKeySize(keys.join("-"));
case "aes128":
return 16;
case "aes192":
return 24;
case "aes256":
return 32;
case "aes":
keys.shift();
return parseInt(keys[0])/8;
case "bf":
case "blowfish":
return 16;
case "des":
keys.shift();
switch (keys[0]) {
case "ede":
return 16;
case "ede3":
return 24;
default:
return 8;
}
case "3des":
case "des3":
return 24;
case "xtea":
return 8;
case "rc4":
if (parseInt(keys[1])>0) {
return parseInt(keys[1])/8;
}
return 16; // why not.
}
return 0; // unknown;
}
private static function getMode(name:String, alg:ISymmetricKey, padding:IPad=null):IMode {
switch (name) {
case "ecb":
return new ECBMode(alg, padding);
case "cfb":
return new CFBMode(alg, padding);
case "cfb8":
return new CFB8Mode(alg, padding);
case "ofb":
return new OFBMode(alg, padding);
case "ctr":
return new CTRMode(alg, padding);
case "cbc":
default:
return new CBCMode(alg, padding);
}
}
/**
* Things that should work:
* "md5"
* "sha"
* "sha1"
* "sha224"
* "sha256"
*/
public static function getHash(name:String):IHash {
switch(name) {
case "md2":
return new MD2;
case "md5":
return new MD5;
case "sha": // let's hope you didn't mean sha-0
case "sha1":
return new SHA1;
case "sha224":
return new SHA224;
case "sha256":
return new SHA256;
}
return null;
}
/**
* Things that should work:
* "sha1"
* "md5-64"
* "hmac-md5-96"
* "hmac-sha1-128"
* "hmac-sha256-192"
* etc.
*/
public static function getHMAC(name:String):HMAC {
var keys:Array = name.split("-");
if (keys[0]=="hmac") keys.shift();
var bits:uint = 0;
if (keys.length>1) {
bits = parseInt(keys[1]);
}
return new HMAC(getHash(keys[0]), bits);
}
public static function getMAC(name:String):MAC {
var keys:Array = name.split("-");
if (keys[0]=="mac") keys.shift();
var bits:uint = 0;
if (keys.length > 1) {
bits = parseInt(keys[1]);
}
return new MAC(getHash(keys[0]), bits);
}
public static function getPad(name:String):IPad {
switch(name) {
case "null":
return new NullPad;
case "pkcs5":
default:
return new PKCS5;
}
}
/** mostly useless.
*/
public static function getRSA(E:String, M:String):RSAKey {
return RSAKey.parsePublicKey(M,E);
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,218 +0,0 @@
/**
* X509Certificate
*
* A representation for a X509 Certificate, with
* methods to parse, verify and sign it.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.cert {
import com.hurlant.crypto.hash.IHash;
import com.hurlant.crypto.hash.MD2;
import com.hurlant.crypto.hash.MD5;
import com.hurlant.crypto.hash.SHA1;
import com.hurlant.crypto.rsa.RSAKey;
import com.hurlant.util.ArrayUtil;
import com.hurlant.util.Base64;
import com.hurlant.util.der.ByteString;
import com.hurlant.util.der.DER;
import com.hurlant.util.der.OID;
import com.hurlant.util.der.ObjectIdentifier;
import com.hurlant.util.der.PEM;
import com.hurlant.util.der.PrintableString;
import com.hurlant.util.der.Sequence;
import com.hurlant.util.der.Type;
import flash.utils.ByteArray;
public class X509Certificate {
private var _loaded:Boolean;
private var _param:*;
private var _obj:Object;
public function X509Certificate(p:*) {
_loaded = false;
_param = p;
// lazy initialization, to avoid unnecessary parsing of every builtin CA at start-up.
}
private function load():void {
if (_loaded) return;
var p:* = _param;
var b:ByteArray;
if (p is String) {
b = PEM.readCertIntoArray(p as String);
} else if (p is ByteArray) {
b = p;
}
if (b!=null) {
_obj = DER.parse(b, Type.TLS_CERT);
_loaded = true;
} else {
throw new Error("Invalid x509 Certificate parameter: "+p);
}
}
public function isSigned(store:X509CertificateCollection, CAs:X509CertificateCollection, time:Date=null):Boolean {
load();
// check timestamps first. cheapest.
if (time==null) {
time = new Date;
}
var notBefore:Date = getNotBefore();
var notAfter:Date = getNotAfter();
if (time.getTime()<notBefore.getTime()) return false; // cert isn't born yet.
if (time.getTime()>notAfter.getTime()) return false; // cert died of old age.
// check signature.
var subject:String = getIssuerPrincipal();
// try from CA first, since they're treated better.
var parent:X509Certificate = CAs.getCertificate(subject);
var parentIsAuthoritative:Boolean = false;
if (parent == null) {
parent = store.getCertificate(subject);
if (parent == null) {
return false; // issuer not found
}
} else {
parentIsAuthoritative = true;
}
if (parent == this) { // pathological case. avoid infinite loop
return false; // isSigned() returns false if we're self-signed.
}
if (!(parentIsAuthoritative&&parent.isSelfSigned(time)) &&
!parent.isSigned(store, CAs, time)) {
return false;
}
var key:RSAKey = parent.getPublicKey();
return verifyCertificate(key);
}
public function isSelfSigned(time:Date):Boolean {
load();
var key:RSAKey = getPublicKey();
return verifyCertificate(key);
}
private function verifyCertificate(key:RSAKey):Boolean {
var algo:String = getAlgorithmIdentifier();
var hash:IHash;
var oid:String;
switch (algo) {
case OID.SHA1_WITH_RSA_ENCRYPTION:
hash = new SHA1;
oid = OID.SHA1_ALGORITHM;
break;
case OID.MD2_WITH_RSA_ENCRYPTION:
hash = new MD2;
oid = OID.MD2_ALGORITHM;
break;
case OID.MD5_WITH_RSA_ENCRYPTION:
hash = new MD5;
oid = OID.MD5_ALGORITHM;
break;
default:
return false;
}
var data:ByteArray = _obj.signedCertificate_bin;
var buf:ByteArray = new ByteArray;
key.verify(_obj.encrypted, buf, _obj.encrypted.length);
buf.position=0;
data = hash.hash(data);
var obj:Object = DER.parse(buf, Type.RSA_SIGNATURE);
if (obj.algorithm.algorithmId.toString() != oid) {
return false; // wrong algorithm
}
if (!ArrayUtil.equals(obj.hash, data)) {
return false; // hashes don't match
}
return true;
}
/**
* This isn't used anywhere so far.
* It would become useful if we started to offer facilities
* to generate and sign X509 certificates.
*
* @param key
* @param algo
* @return
*
*/
private function signCertificate(key:RSAKey, algo:String):ByteArray {
var hash:IHash;
var oid:String;
switch (algo) {
case OID.SHA1_WITH_RSA_ENCRYPTION:
hash = new SHA1;
oid = OID.SHA1_ALGORITHM;
break;
case OID.MD2_WITH_RSA_ENCRYPTION:
hash = new MD2;
oid = OID.MD2_ALGORITHM;
break;
case OID.MD5_WITH_RSA_ENCRYPTION:
hash = new MD5;
oid = OID.MD5_ALGORITHM;
break;
default:
return null
}
var data:ByteArray = _obj.signedCertificate_bin;
data = hash.hash(data);
var seq1:Sequence = new Sequence;
seq1[0] = new Sequence;
seq1[0][0] = new ObjectIdentifier(0,0, oid);
seq1[0][1] = null;
seq1[1] = new ByteString;
seq1[1].writeBytes(data);
data = seq1.toDER();
var buf:ByteArray = new ByteArray;
key.sign(data, buf, data.length);
return buf;
}
public function getPublicKey():RSAKey {
load();
var pk:ByteArray = _obj.signedCertificate.subjectPublicKeyInfo.subjectPublicKey as ByteArray;
pk.position = 0;
var rsaKey:Object = DER.parse(pk, [{name:"N"},{name:"E"}]);
return new RSAKey(rsaKey.N, rsaKey.E.valueOf());
}
/**
* Returns a subject principal, as an opaque base64 string.
* This is only used as a hash key for known certificates.
*
* Note that this assumes X509 DER-encoded certificates are uniquely encoded,
* as we look for exact matches between Issuer and Subject fields.
*
*/
public function getSubjectPrincipal():String {
load();
return Base64.encodeByteArray(_obj.signedCertificate.subject_bin);
}
/**
* Returns an issuer principal, as an opaque base64 string.
* This is only used to quickly find matching parent certificates.
*
* Note that this assumes X509 DER-encoded certificates are uniquely encoded,
* as we look for exact matches between Issuer and Subject fields.
*
*/
public function getIssuerPrincipal():String {
load();
return Base64.encodeByteArray(_obj.signedCertificate.issuer_bin);
}
public function getAlgorithmIdentifier():String {
return _obj.algorithmIdentifier.algorithmId.toString();
}
public function getNotBefore():Date {
return _obj.signedCertificate.validity.notBefore.date;
}
public function getNotAfter():Date {
return _obj.signedCertificate.validity.notAfter.date;
}
public function getCommonName():String {
var subject:Sequence = _obj.signedCertificate.subject;
return (subject.findAttributeValue(OID.COMMON_NAME) as PrintableString).getString();
}
}
}
@@ -1,57 +0,0 @@
/**
* X509CertificateCollection
*
* A class to store and index X509 Certificates by Subject.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.cert {
public class X509CertificateCollection {
private var _map:Object;
public function X509CertificateCollection() {
_map = {};
}
/**
* Mostly meant for built-in CA loading.
* This entry-point allows to index CAs without parsing them.
*
* @param name A friendly name. not currently used
* @param subject base64 DER encoded Subject principal for the Cert
* @param pem PEM encoded certificate data
*
*/
public function addPEMCertificate(name:String, subject:String, pem:String):void {
_map[subject] = new X509Certificate(pem);
}
/**
* Adds a X509 certificate to the collection.
* This call will force the certificate to be parsed.
*
* @param cert A X509 certificate
*
*/
public function addCertificate(cert:X509Certificate):void {
var subject:String = cert.getSubjectPrincipal();
_map[subject] = cert;
}
/**
* Returns a X509 Certificate present in the collection, given
* a base64 DER encoded X500 Subject principal
*
* @param subject A Base64 DER-encoded Subject principal
* @return A matching certificate, or null.
*
*/
public function getCertificate(subject:String):X509Certificate {
return _map[subject];
}
}
}
@@ -1,65 +0,0 @@
K 25
svn:wc:ra_dav:version-url
V 60
/svn/!svn/ver/28/trunk/as3crypto/src/com/hurlant/crypto/hash
END
MAC.as
K 25
svn:wc:ra_dav:version-url
V 67
/svn/!svn/ver/28/trunk/as3crypto/src/com/hurlant/crypto/hash/MAC.as
END
IHMAC.as
K 25
svn:wc:ra_dav:version-url
V 69
/svn/!svn/ver/28/trunk/as3crypto/src/com/hurlant/crypto/hash/IHMAC.as
END
MD2.as
K 25
svn:wc:ra_dav:version-url
V 67
/svn/!svn/ver/28/trunk/as3crypto/src/com/hurlant/crypto/hash/MD2.as
END
SHA224.as
K 25
svn:wc:ra_dav:version-url
V 69
/svn/!svn/ver/3/trunk/as3crypto/src/com/hurlant/crypto/hash/SHA224.as
END
MD5.as
K 25
svn:wc:ra_dav:version-url
V 67
/svn/!svn/ver/28/trunk/as3crypto/src/com/hurlant/crypto/hash/MD5.as
END
SHABase.as
K 25
svn:wc:ra_dav:version-url
V 71
/svn/!svn/ver/28/trunk/as3crypto/src/com/hurlant/crypto/hash/SHABase.as
END
SHA256.as
K 25
svn:wc:ra_dav:version-url
V 70
/svn/!svn/ver/28/trunk/as3crypto/src/com/hurlant/crypto/hash/SHA256.as
END
HMAC.as
K 25
svn:wc:ra_dav:version-url
V 68
/svn/!svn/ver/28/trunk/as3crypto/src/com/hurlant/crypto/hash/HMAC.as
END
IHash.as
K 25
svn:wc:ra_dav:version-url
V 69
/svn/!svn/ver/28/trunk/as3crypto/src/com/hurlant/crypto/hash/IHash.as
END
SHA1.as
K 25
svn:wc:ra_dav:version-url
V 68
/svn/!svn/ver/28/trunk/as3crypto/src/com/hurlant/crypto/hash/SHA1.as
END
@@ -1,368 +0,0 @@
10
dir
28
http://as3crypto.googlecode.com/svn/trunk/as3crypto/src/com/hurlant/crypto/hash
http://as3crypto.googlecode.com/svn
2009-06-04T23:35:21.192697Z
28
sh0rtwave
395c722c-794e-0410-9327-f1aa524df581
MAC.as
file
2009-11-07T06:59:45.000000Z
0bedba9be73ae40adeb26ca35c8237f4
2009-06-04T23:35:21.192697Z
28
sh0rtwave
has-props
3559
IHMAC.as
file
2009-11-07T06:59:45.000000Z
dac8b7d8c849fe11f90ec290aa5dedf0
2009-06-04T23:35:21.192697Z
28
sh0rtwave
has-props
599
MD2.as
file
2009-11-07T06:59:45.000000Z
73bf759d445a65186512066a103dbb45
2009-06-04T23:35:21.192697Z
28
sh0rtwave
3811
SHA224.as
file
2009-11-07T06:59:45.000000Z
026d3e96099de7100c1d49012720d6f9
2008-06-22T05:51:59.360556Z
3
henrit
604
MD5.as
file
2009-11-07T06:59:45.000000Z
60211f6583ee826e2a17ad03605aa7b4
2009-06-04T23:35:21.192697Z
28
sh0rtwave
6965
SHABase.as
file
2009-11-07T06:59:45.000000Z
aa1101bf874f26cd364cf16fb7dff6c7
2009-06-04T23:35:21.192697Z
28
sh0rtwave
1495
SHA256.as
file
2009-11-07T06:59:45.000000Z
c14bc0555970db81a87f5d2b60e4288c
2009-06-04T23:35:21.192697Z
28
sh0rtwave
3459
HMAC.as
file
2009-11-07T06:59:45.000000Z
c96c9bc0e0b64eed7e2d8c27dc29c561
2009-06-04T23:35:21.192697Z
28
sh0rtwave
2132
IHash.as
file
2009-11-07T06:59:45.000000Z
71f45750c456debd7ef1f74e6db9dc23
2009-06-04T23:35:21.192697Z
28
sh0rtwave
445
SHA1.as
file
2009-11-07T06:59:45.000000Z
ba97b95bebda5bdd3fe2063e9c7e21cd
2009-06-04T23:35:21.192697Z
28
sh0rtwave
2642
@@ -1,5 +0,0 @@
K 14
svn:executable
V 1
*
END
@@ -1,5 +0,0 @@
K 14
svn:executable
V 1
*
END
@@ -1,82 +0,0 @@
/**
* HMAC
*
* An ActionScript 3 implementation of HMAC, Keyed-Hashing for Message
* Authentication, as defined by RFC-2104
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
import com.hurlant.util.Hex;
public class HMAC implements IHMAC
{
private var hash:IHash;
private var bits:uint;
/**
* Create a HMAC object, using a Hash function, and
* optionally a number of bits to return.
* The HMAC will be truncated to that size if needed.
*/
public function HMAC(hash:IHash, bits:uint=0) {
this.hash = hash;
this.bits = bits;
}
public function getHashSize():uint {
if (bits!=0) {
return bits/8;
} else {
return hash.getHashSize();
}
}
/**
* Compute a HMAC using a key and some data.
* It doesn't modify either, and returns a new ByteArray with the HMAC value.
*/
public function compute(key:ByteArray, data:ByteArray):ByteArray {
var hashKey:ByteArray;
if (key.length>hash.getInputSize()) {
hashKey = hash.hash(key);
} else {
hashKey = new ByteArray;
hashKey.writeBytes(key);
}
while (hashKey.length<hash.getInputSize()) {
hashKey[hashKey.length]=0;
}
var innerKey:ByteArray = new ByteArray;
var outerKey:ByteArray = new ByteArray;
for (var i:uint=0;i<hashKey.length;i++) {
innerKey[i] = hashKey[i] ^ 0x36;
outerKey[i] = hashKey[i] ^ 0x5c;
}
// inner + data
innerKey.position = hashKey.length;
innerKey.writeBytes(data);
var innerHash:ByteArray = hash.hash(innerKey);
// outer + innerHash
outerKey.position = hashKey.length;
outerKey.writeBytes(innerHash);
var outerHash:ByteArray = hash.hash(outerKey);
if (bits>0 && bits<8*outerHash.length) {
outerHash.length = bits/8;
}
return outerHash;
}
public function dispose():void {
hash = null;
bits = 0;
}
public function toString():String {
return "hmac-"+(bits>0?bits+"-":"")+hash.toString();
}
}
}
@@ -1,27 +0,0 @@
/**
* HMAC
*
* An ActionScript 3 interface for HMAC & MAC
* implementations.
*
* Loosely copyrighted by Bobby Parker
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
public interface IHMAC
{
function getHashSize():uint;
/**
* Compute a HMAC using a key and some data.
* It doesn't modify either, and returns a new ByteArray with the HMAC value.
*/
function compute(key:ByteArray, data:ByteArray):ByteArray;
function dispose():void;
function toString():String;
}
}
@@ -1,21 +0,0 @@
/**
* IHash
*
* An interface for each hash function to implement
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
public interface IHash
{
function getInputSize():uint;
function getHashSize():uint;
function hash(src:ByteArray):ByteArray;
function toString():String;
function getPadSize():int;
}
}
@@ -1,137 +0,0 @@
/**
* MAC
*
* An ActionScript 3 implementation of MAC, Message Authentication Code
* for use with SSL 3.0.
* Loosely copyrighted by Bobby Parker.
* As3crypto copyrighted by Henri Torgemane.
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
import com.hurlant.util.Hex;
public class MAC implements IHMAC
{
private var hash:IHash;
private var bits:uint;
private var pad_1:ByteArray;
private var pad_2:ByteArray;
private var innerHash:ByteArray;
private var outerHash:ByteArray;
private var outerKey:ByteArray;
private var innerKey:ByteArray;
/**
* Create a MAC object (for SSL 3.0 ) and
* optionally a number of bits to return.
* The MAC will be truncated to that size if needed.
*/
public function MAC(hash:IHash, bits:uint=0) {
this.hash = hash;
this.bits = bits;
innerHash = new ByteArray();
outerHash = new ByteArray();
innerKey = new ByteArray();
outerKey = new ByteArray();
if (hash != null) {
var pad_size:int = hash.getPadSize();
pad_1 = new ByteArray();
pad_2 = new ByteArray();
for (var x:int = 0; x < pad_size; x++) {
pad_1.writeByte(0x36);
pad_2.writeByte(0x5c);
}
}
}
public function setPadSize(pad_size:int) : void { }
public function getHashSize():uint {
if (bits!=0) {
return bits/8;
} else {
return hash.getHashSize();
}
}
/**
* Compute a MAC using a key and some data.
*
*/
public function compute(key:ByteArray, data:ByteArray):ByteArray {
// take that incoming key and do hash(key + pad_2 + hash(key + pad_1 + sequence + length + record)
// note that data = (sequence + type + length + record)
if (pad_1 == null) {
var pad_size:int = hash.getPadSize();
pad_1 = new ByteArray();
pad_2 = new ByteArray();
for (var x:int = 0; x < pad_size; x++) {
pad_1.writeByte(0x36);
pad_2.writeByte(0x5c);
}
}
// Do some preliminary checking on stuff
/*
if (key.length > hash.getInputSize()) {
hashKey = hash.hash(key);
} else {
hashKey = new ByteArray;
hashKey.writeBytes(key);
}
while (hashKey.length < hash.getInputSize() ) {
hashKey[hashKey.length] = 0;
} */
// Henri's conventions work just fine here..
innerKey.length = 0;
outerKey.length = 0;
// trace("MAC Key: " + Hex.fromArray(key));
// trace("Key Length: " + key.length);
// trace("Pad_1 : " + Hex.fromArray(pad_1));
// inner hash calc
innerKey.writeBytes(key);
innerKey.writeBytes(pad_1);
innerKey.writeBytes(data);
// trace("MAC Inner Key: " + Hex.fromArray(innerKey));
innerHash = hash.hash(innerKey);
// trace("MAC Inner Hash: " + Hex.fromArray(innerHash));
// outer hash calc
outerKey.writeBytes(key);
outerKey.writeBytes(pad_2);
outerKey.writeBytes(innerHash);
// trace("MAC Outer Key: " + Hex.fromArray(outerKey));
outerHash = hash.hash(outerKey);
if (bits > 0 && bits < 8*outerHash.length) {
outerHash.length = bits/8;
}
// trace("MAC for record: " + Hex.fromArray(outerHash));
return outerHash;
}
public function dispose():void {
hash = null;
bits = 0;
}
public function toString():String {
return "mac-"+(bits>0?bits+"-":"")+hash.toString();
}
}
}
@@ -1,121 +0,0 @@
/**
* MD2
*
* An ActionScript 3 implementation of the RSA Data Security, Inc MD2 Message
* Digest Algorithm, as defined in RFC 1319
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*
* Excerpt from http://en.wikipedia.org/wiki/MD2:
* >
* > Rogier and Chauvaud (1997) described collisions of MD2's compression function,
* > although they were unable to extend the attack to the full MD2.
* >
* > In 2004, MD2 was shown to be vulnerable to a preimage attack with time
* > complexity equivalent to 2104 applications of the compression function
* > (Muller, 2004).
* > The author concludes, "MD2 can no longer be considered a secure one-way
* > hash function".
*
* also, this implementaton is quite slow.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
public class MD2 implements IHash
{
public static const HASH_SIZE:int = 16;
public var pad_size:int = 48; // probably will never get used, only here for SSL 3.0 support
private static const S:Array = [ // PI Digits
41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, 19,
98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, 76, 130, 202,
30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, 138, 23, 229, 18,
190, 78, 196, 214, 218, 158, 222, 73, 160, 251, 245, 142, 187, 47, 238, 122,
169, 104, 121, 145, 21, 178, 7, 63, 148, 194, 16, 137, 11, 34, 95, 33,
128, 127, 93, 154, 90, 144, 50, 39, 53, 62, 204, 231, 191, 247, 151, 3,
255, 25, 48, 179, 72, 165, 181, 209, 215, 94, 146, 42, 172, 86, 170, 198,
79, 184, 56, 210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241,
69, 157, 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2,
27, 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, 234, 38,
44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, 129, 77, 82,
106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, 8, 12, 189, 177, 74,
120, 136, 149, 139, 227, 99, 232, 109, 233, 203, 213, 254, 59, 0, 29, 57,
242, 239, 183, 14, 102, 88, 208, 228, 166, 119, 114, 248, 235, 117, 75, 10,
49, 68, 80, 180, 143, 237, 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 ];
public function getInputSize():uint
{
return 16;
}
public function getPadSize():int {
return pad_size;
}
public function getHashSize():uint
{
return HASH_SIZE;
}
public function hash(src:ByteArray):ByteArray
{
var savedLength:uint = src.length;
// 3.1 Step 1. Padding
var i:uint = (16-src.length%16) || 16;
do {
src[src.length]=i;
} while (src.length%16!=0);
// 3.2 Step 2. Checksum
var len:uint = src.length;
var checksum:ByteArray = new ByteArray;
var L:uint = 0;
for (i = 0;i<len;i+=16) {
for (var j:uint=0;j<16;j++) {
L = checksum[j] ^= S[src[i+j] ^ L];
}
}
src.position = src.length;
src.writeBytes(checksum);
len += 16;
// 3.3 Step 3. MD Buffer
var X:ByteArray = new ByteArray;
// 3.4 Process Message
for (i=0;i<len;i+=16) {
/* Copy block i into X */
for (j=0;j<16;j++) {
X[32+j] = (X[16+j] = src[i+j])^X[j];
}
var t:uint=0;
/* Do 18 rounds */
for (j=0;j<18;j++) {
/* Round j. */
for (var k:uint=0;k<48;k++) {
X[k] = t = X[k]^S[t];
}
t = (t+j)&0xff;
}
}
// 3.5 Step 5. Output
X.length = 16;
// restore original length;
src.length = savedLength;
return X;
}
public function toString():String
{
return "md2";
}
}
}
@@ -1,202 +0,0 @@
/**
* MD5
*
* An ActionScript 3 implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Copyright (c) 2007 Henri Torgemane
*
* Derived from
* A JavaScript implementation of the same.
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
*
* Note:
* This algorithm should not be your first choice for new developements, but is
* included to allow interoperability with existing codes and protocols.
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
import flash.utils.Endian;
public class MD5 implements IHash
{
public static const HASH_SIZE:int = 16;
public var pad_size:int = 48;
public function getInputSize():uint
{
return 64;
}
public function getHashSize():uint
{
return HASH_SIZE;
}
public function getPadSize():int
{
return pad_size;
}
public function hash(src:ByteArray):ByteArray
{
var len:uint = src.length *8;
var savedEndian:String = src.endian;
// pad to nearest int.
while (src.length%4!=0) {
src[src.length]=0;
}
// convert ByteArray to an array of uint
src.position=0;
var a:Array = [];
src.endian=Endian.LITTLE_ENDIAN
for (var i:uint=0;i<src.length;i+=4) {
a.push(src.readUnsignedInt());
}
var h:Array = core_md5(a, len);
var out:ByteArray = new ByteArray;
out.endian=Endian.LITTLE_ENDIAN;
for (i=0;i<4;i++) {
out.writeUnsignedInt(h[i]);
}
// restore length!
src.length = len/8;
src.endian = savedEndian;
return out;
}
private function core_md5(x:Array, len:uint):Array {
/* append padding */
x[len >> 5] |= 0x80 << ((len) % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;
var a:uint = 0x67452301; // 1732584193;
var b:uint = 0xEFCDAB89; //-271733879;
var c:uint = 0x98BADCFE; //-1732584194;
var d:uint = 0x10325476; // 271733878;
for(var i:uint = 0; i < x.length; i += 16)
{
x[i]||=0; x[i+1]||=0; x[i+2]||=0; x[i+3]||=0;
x[i+4]||=0; x[i+5]||=0; x[i+6]||=0; x[i+7]||=0;
x[i+8]||=0; x[i+9]||=0; x[i+10]||=0; x[i+11]||=0;
x[i+12]||=0; x[i+13]||=0; x[i+14]||=0; x[i+15]||=0;
var olda:uint = a;
var oldb:uint = b;
var oldc:uint = c;
var oldd:uint = d;
a = ff(a, b, c, d, x[i+ 0], 7 , 0xD76AA478);
d = ff(d, a, b, c, x[i+ 1], 12, 0xE8C7B756);
c = ff(c, d, a, b, x[i+ 2], 17, 0x242070DB);
b = ff(b, c, d, a, x[i+ 3], 22, 0xC1BDCEEE);
a = ff(a, b, c, d, x[i+ 4], 7 , 0xF57C0FAF);
d = ff(d, a, b, c, x[i+ 5], 12, 0x4787C62A);
c = ff(c, d, a, b, x[i+ 6], 17, 0xA8304613);
b = ff(b, c, d, a, x[i+ 7], 22, 0xFD469501);
a = ff(a, b, c, d, x[i+ 8], 7 , 0x698098D8);
d = ff(d, a, b, c, x[i+ 9], 12, 0x8B44F7AF);
c = ff(c, d, a, b, x[i+10], 17, 0xFFFF5BB1);
b = ff(b, c, d, a, x[i+11], 22, 0x895CD7BE);
a = ff(a, b, c, d, x[i+12], 7 , 0x6B901122);
d = ff(d, a, b, c, x[i+13], 12, 0xFD987193);
c = ff(c, d, a, b, x[i+14], 17, 0xA679438E);
b = ff(b, c, d, a, x[i+15], 22, 0x49B40821);
a = gg(a, b, c, d, x[i+ 1], 5 , 0xf61e2562);
d = gg(d, a, b, c, x[i+ 6], 9 , 0xc040b340);
c = gg(c, d, a, b, x[i+11], 14, 0x265e5a51);
b = gg(b, c, d, a, x[i+ 0], 20, 0xe9b6c7aa);
a = gg(a, b, c, d, x[i+ 5], 5 , 0xd62f105d);
d = gg(d, a, b, c, x[i+10], 9 , 0x2441453);
c = gg(c, d, a, b, x[i+15], 14, 0xd8a1e681);
b = gg(b, c, d, a, x[i+ 4], 20, 0xe7d3fbc8);
a = gg(a, b, c, d, x[i+ 9], 5 , 0x21e1cde6);
d = gg(d, a, b, c, x[i+14], 9 , 0xc33707d6);
c = gg(c, d, a, b, x[i+ 3], 14, 0xf4d50d87);
b = gg(b, c, d, a, x[i+ 8], 20, 0x455a14ed);
a = gg(a, b, c, d, x[i+13], 5 , 0xa9e3e905);
d = gg(d, a, b, c, x[i+ 2], 9 , 0xfcefa3f8);
c = gg(c, d, a, b, x[i+ 7], 14, 0x676f02d9);
b = gg(b, c, d, a, x[i+12], 20, 0x8d2a4c8a);
a = hh(a, b, c, d, x[i+ 5], 4 , 0xfffa3942);
d = hh(d, a, b, c, x[i+ 8], 11, 0x8771f681);
c = hh(c, d, a, b, x[i+11], 16, 0x6d9d6122);
b = hh(b, c, d, a, x[i+14], 23, 0xfde5380c);
a = hh(a, b, c, d, x[i+ 1], 4 , 0xa4beea44);
d = hh(d, a, b, c, x[i+ 4], 11, 0x4bdecfa9);
c = hh(c, d, a, b, x[i+ 7], 16, 0xf6bb4b60);
b = hh(b, c, d, a, x[i+10], 23, 0xbebfbc70);
a = hh(a, b, c, d, x[i+13], 4 , 0x289b7ec6);
d = hh(d, a, b, c, x[i+ 0], 11, 0xeaa127fa);
c = hh(c, d, a, b, x[i+ 3], 16, 0xd4ef3085);
b = hh(b, c, d, a, x[i+ 6], 23, 0x4881d05);
a = hh(a, b, c, d, x[i+ 9], 4 , 0xd9d4d039);
d = hh(d, a, b, c, x[i+12], 11, 0xe6db99e5);
c = hh(c, d, a, b, x[i+15], 16, 0x1fa27cf8);
b = hh(b, c, d, a, x[i+ 2], 23, 0xc4ac5665);
a = ii(a, b, c, d, x[i+ 0], 6 , 0xf4292244);
d = ii(d, a, b, c, x[i+ 7], 10, 0x432aff97);
c = ii(c, d, a, b, x[i+14], 15, 0xab9423a7);
b = ii(b, c, d, a, x[i+ 5], 21, 0xfc93a039);
a = ii(a, b, c, d, x[i+12], 6 , 0x655b59c3);
d = ii(d, a, b, c, x[i+ 3], 10, 0x8f0ccc92);
c = ii(c, d, a, b, x[i+10], 15, 0xffeff47d);
b = ii(b, c, d, a, x[i+ 1], 21, 0x85845dd1);
a = ii(a, b, c, d, x[i+ 8], 6 , 0x6fa87e4f);
d = ii(d, a, b, c, x[i+15], 10, 0xfe2ce6e0);
c = ii(c, d, a, b, x[i+ 6], 15, 0xa3014314);
b = ii(b, c, d, a, x[i+13], 21, 0x4e0811a1);
a = ii(a, b, c, d, x[i+ 4], 6 , 0xf7537e82);
d = ii(d, a, b, c, x[i+11], 10, 0xbd3af235);
c = ii(c, d, a, b, x[i+ 2], 15, 0x2ad7d2bb);
b = ii(b, c, d, a, x[i+ 9], 21, 0xeb86d391);
a += olda;
b += oldb;
c += oldc;
d += oldd;
}
return [ a, b, c, d ];
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
private function rol(num:uint, cnt:uint):uint
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* These functions implement the four basic operations the algorithm uses.
*/
private function cmn(q:uint, a:uint, b:uint, x:uint, s:uint, t:uint):uint {
return rol(a + q + x + t, s) + b;
}
private function ff(a:uint, b:uint, c:uint, d:uint, x:uint, s:uint, t:uint):uint {
return cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
private function gg(a:uint, b:uint, c:uint, d:uint, x:uint, s:uint, t:uint):uint {
return cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
private function hh(a:uint, b:uint, c:uint, d:uint, x:uint, s:uint, t:uint):uint {
return cmn(b ^ c ^ d, a, b, x, s, t);
}
private function ii(a:uint, b:uint, c:uint, d:uint, x:uint, s:uint, t:uint):uint {
return cmn(c ^ (b | (~d)), a, b, x, s, t);
}
public function toString():String {
return "md5";
}
}
}
@@ -1,106 +0,0 @@
/**
* SHA1
*
* An ActionScript 3 implementation of Secure Hash Algorithm, SHA-1, as defined
* in FIPS PUB 180-1
* Copyright (c) 2007 Henri Torgemane
*
* Derived from:
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
* in FIPS PUB 180-1
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
public class SHA1 extends SHABase implements IHash
{
public static const HASH_SIZE:int = 20;
public override function getHashSize():uint {
return HASH_SIZE;
}
protected override function core(x:Array, len:uint):Array
{
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w:Array = [];
var a:uint = 0x67452301; //1732584193;
var b:uint = 0xEFCDAB89; //-271733879;
var c:uint = 0x98BADCFE; //-1732584194;
var d:uint = 0x10325476; //271733878;
var e:uint = 0xC3D2E1F0; //-1009589776;
for(var i:uint = 0; i < x.length; i += 16)
{
var olda:uint = a;
var oldb:uint = b;
var oldc:uint = c;
var oldd:uint = d;
var olde:uint = e;
for(var j:uint = 0; j < 80; j++)
{
if (j < 16) {
w[j] = x[i + j] || 0;
} else {
w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
}
var t:uint = rol(a,5) + ft(j,b,c,d) + e + w[j] + kt(j);
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a += olda;
b += oldb;
c += oldc;
d += oldd;
e += olde;
}
return [ a, b, c, d, e ];
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
private function rol(num:uint, cnt:uint):uint
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
private function ft(t:uint, b:uint, c:uint, d:uint):uint
{
if(t < 20) return (b & c) | ((~b) & d);
if(t < 40) return b ^ c ^ d;
if(t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
private function kt(t:uint):uint
{
return (t < 20) ? 0x5A827999 : (t < 40) ? 0x6ED9EBA1 :
(t < 60) ? 0x8F1BBCDC : 0xCA62C1D6;
}
public override function toString():String {
return "sha1";
}
}
}
@@ -1,28 +0,0 @@
/**
* SHA224
*
* An ActionScript 3 implementation of Secure Hash Algorithm, SHA-224, as defined
* in FIPS PUB 180-2
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
public class SHA224 extends SHA256
{
function SHA224() {
h = [
0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
];
}
public override function getHashSize():uint {
return 28;
}
public override function toString():String {
return "sha224";
}
}
}
@@ -1,115 +0,0 @@
/**
* SHA256
*
* An ActionScript 3 implementation of Secure Hash Algorithm, SHA-256, as defined
* in FIPS PUB 180-2
* Copyright (c) 2007 Henri Torgemane
*
* Derived from:
* A JavaScript implementation of the Secure Hash Standard
* Version 0.3 Copyright Angel Marin 2003-2004 - http://anmar.eu.org/
* Derived from:
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
* in FIPS PUB 180-1
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
public class SHA256 extends SHABase implements IHash
{
protected static const k:Array = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2];
protected var h:Array = [
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
];
public function SHA256(){
}
public override function getHashSize():uint
{
return 32;
}
protected override function core(x:Array, len:uint):Array {
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w:Array = [];
var a:uint = h[0];
var b:uint = h[1];
var c:uint = h[2];
var d:uint = h[3];
var e:uint = h[4];
var f:uint = h[5];
var g:uint = h[6];
var h:uint = h[7];
for (var i:uint=0; i<x.length; i+=16) {
var olda:uint = a;
var oldb:uint = b;
var oldc:uint = c;
var oldd:uint = d;
var olde:uint = e;
var oldf:uint = f;
var oldg:uint = g;
var oldh:uint = h;
for (var j:uint=0; j<64; j++) {
if (j<16) {
w[j] = x[i+j] || 0;
} else {
var s0:uint = rrol(w[j-15],7)^rrol(w[j-15],18)^(w[j-15]>>>3);
var s1:uint = rrol(w[j-2], 17)^rrol(w[j-2],19)^(w[j-2]>>>10);
w[j] = w[j-16] + s0 + w[j-7] + s1;
}
var t2:uint = (rrol(a,2) ^ rrol(a,13) ^ rrol(a,22)) + ((a&b) ^ (a&c) ^ (b&c));
var t1:uint = h + (rrol(e,6) ^ rrol(e,11) ^ rrol(e,25)) + ((e&f)^(g&~e)) + k[j] + w[j]
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
a += olda;
b += oldb;
c += oldc;
d += oldd;
e += olde;
f += oldf;
g += oldg;
h += oldh;
}
return [ a,b,c,d,e,f,g,h ];
}
/*
* Bitwise rotate a 32-bit number to the right.
*/
protected function rrol(num:uint, cnt:uint):uint {
return (num << (32-cnt)) | (num >>> cnt);
}
public override function toString():String {
return "sha256";
}
}
}
@@ -1,68 +0,0 @@
/**
* SHABase
*
* An ActionScript 3 abstract class for the SHA family of hash functions
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
import flash.utils.Endian;
public class SHABase implements IHash
{
public var pad_size:int = 40;
public function getInputSize():uint
{
return 64;
}
public function getHashSize():uint
{
return 0;
}
public function getPadSize():int
{
return pad_size;
}
public function hash(src:ByteArray):ByteArray
{
var savedLength:uint = src.length;
var savedEndian:String = src.endian;
src.endian = Endian.BIG_ENDIAN;
var len:uint = savedLength *8;
// pad to nearest int.
while (src.length%4!=0) {
src[src.length]=0;
}
// convert ByteArray to an array of uint
src.position=0;
var a:Array = [];
for (var i:uint=0;i<src.length;i+=4) {
a.push(src.readUnsignedInt());
}
var h:Array = core(a, len);
var out:ByteArray = new ByteArray;
var words:uint = getHashSize()/4;
for (i=0;i<words;i++) {
out.writeUnsignedInt(h[i]);
}
// unpad, to leave the source untouched.
src.length = savedLength;
src.endian = savedEndian;
return out;
}
protected function core(x:Array, len:uint):Array {
return null;
}
public function toString():String {
return "sha";
}
}
}
@@ -1,82 +0,0 @@
/**
* HMAC
*
* An ActionScript 3 implementation of HMAC, Keyed-Hashing for Message
* Authentication, as defined by RFC-2104
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
import com.hurlant.util.Hex;
public class HMAC implements IHMAC
{
private var hash:IHash;
private var bits:uint;
/**
* Create a HMAC object, using a Hash function, and
* optionally a number of bits to return.
* The HMAC will be truncated to that size if needed.
*/
public function HMAC(hash:IHash, bits:uint=0) {
this.hash = hash;
this.bits = bits;
}
public function getHashSize():uint {
if (bits!=0) {
return bits/8;
} else {
return hash.getHashSize();
}
}
/**
* Compute a HMAC using a key and some data.
* It doesn't modify either, and returns a new ByteArray with the HMAC value.
*/
public function compute(key:ByteArray, data:ByteArray):ByteArray {
var hashKey:ByteArray;
if (key.length>hash.getInputSize()) {
hashKey = hash.hash(key);
} else {
hashKey = new ByteArray;
hashKey.writeBytes(key);
}
while (hashKey.length<hash.getInputSize()) {
hashKey[hashKey.length]=0;
}
var innerKey:ByteArray = new ByteArray;
var outerKey:ByteArray = new ByteArray;
for (var i:uint=0;i<hashKey.length;i++) {
innerKey[i] = hashKey[i] ^ 0x36;
outerKey[i] = hashKey[i] ^ 0x5c;
}
// inner + data
innerKey.position = hashKey.length;
innerKey.writeBytes(data);
var innerHash:ByteArray = hash.hash(innerKey);
// outer + innerHash
outerKey.position = hashKey.length;
outerKey.writeBytes(innerHash);
var outerHash:ByteArray = hash.hash(outerKey);
if (bits>0 && bits<8*outerHash.length) {
outerHash.length = bits/8;
}
return outerHash;
}
public function dispose():void {
hash = null;
bits = 0;
}
public function toString():String {
return "hmac-"+(bits>0?bits+"-":"")+hash.toString();
}
}
}
@@ -1,27 +0,0 @@
/**
* HMAC
*
* An ActionScript 3 interface for HMAC & MAC
* implementations.
*
* Loosely copyrighted by Bobby Parker
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
public interface IHMAC
{
function getHashSize():uint;
/**
* Compute a HMAC using a key and some data.
* It doesn't modify either, and returns a new ByteArray with the HMAC value.
*/
function compute(key:ByteArray, data:ByteArray):ByteArray;
function dispose():void;
function toString():String;
}
}
@@ -1,21 +0,0 @@
/**
* IHash
*
* An interface for each hash function to implement
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
public interface IHash
{
function getInputSize():uint;
function getHashSize():uint;
function hash(src:ByteArray):ByteArray;
function toString():String;
function getPadSize():int;
}
}
@@ -1,137 +0,0 @@
/**
* MAC
*
* An ActionScript 3 implementation of MAC, Message Authentication Code
* for use with SSL 3.0.
* Loosely copyrighted by Bobby Parker.
* As3crypto copyrighted by Henri Torgemane.
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
import com.hurlant.util.Hex;
public class MAC implements IHMAC
{
private var hash:IHash;
private var bits:uint;
private var pad_1:ByteArray;
private var pad_2:ByteArray;
private var innerHash:ByteArray;
private var outerHash:ByteArray;
private var outerKey:ByteArray;
private var innerKey:ByteArray;
/**
* Create a MAC object (for SSL 3.0 ) and
* optionally a number of bits to return.
* The MAC will be truncated to that size if needed.
*/
public function MAC(hash:IHash, bits:uint=0) {
this.hash = hash;
this.bits = bits;
innerHash = new ByteArray();
outerHash = new ByteArray();
innerKey = new ByteArray();
outerKey = new ByteArray();
if (hash != null) {
var pad_size:int = hash.getPadSize();
pad_1 = new ByteArray();
pad_2 = new ByteArray();
for (var x:int = 0; x < pad_size; x++) {
pad_1.writeByte(0x36);
pad_2.writeByte(0x5c);
}
}
}
public function setPadSize(pad_size:int) : void { }
public function getHashSize():uint {
if (bits!=0) {
return bits/8;
} else {
return hash.getHashSize();
}
}
/**
* Compute a MAC using a key and some data.
*
*/
public function compute(key:ByteArray, data:ByteArray):ByteArray {
// take that incoming key and do hash(key + pad_2 + hash(key + pad_1 + sequence + length + record)
// note that data = (sequence + type + length + record)
if (pad_1 == null) {
var pad_size:int = hash.getPadSize();
pad_1 = new ByteArray();
pad_2 = new ByteArray();
for (var x:int = 0; x < pad_size; x++) {
pad_1.writeByte(0x36);
pad_2.writeByte(0x5c);
}
}
// Do some preliminary checking on stuff
/*
if (key.length > hash.getInputSize()) {
hashKey = hash.hash(key);
} else {
hashKey = new ByteArray;
hashKey.writeBytes(key);
}
while (hashKey.length < hash.getInputSize() ) {
hashKey[hashKey.length] = 0;
} */
// Henri's conventions work just fine here..
innerKey.length = 0;
outerKey.length = 0;
// trace("MAC Key: " + Hex.fromArray(key));
// trace("Key Length: " + key.length);
// trace("Pad_1 : " + Hex.fromArray(pad_1));
// inner hash calc
innerKey.writeBytes(key);
innerKey.writeBytes(pad_1);
innerKey.writeBytes(data);
// trace("MAC Inner Key: " + Hex.fromArray(innerKey));
innerHash = hash.hash(innerKey);
// trace("MAC Inner Hash: " + Hex.fromArray(innerHash));
// outer hash calc
outerKey.writeBytes(key);
outerKey.writeBytes(pad_2);
outerKey.writeBytes(innerHash);
// trace("MAC Outer Key: " + Hex.fromArray(outerKey));
outerHash = hash.hash(outerKey);
if (bits > 0 && bits < 8*outerHash.length) {
outerHash.length = bits/8;
}
// trace("MAC for record: " + Hex.fromArray(outerHash));
return outerHash;
}
public function dispose():void {
hash = null;
bits = 0;
}
public function toString():String {
return "mac-"+(bits>0?bits+"-":"")+hash.toString();
}
}
}
@@ -1,124 +0,0 @@
/**
* MD2
*
* An ActionScript 3 implementation of the RSA Data Security, Inc MD2 Message
* Digest Algorithm, as defined in RFC 1319
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*
* Excerpt from http://en.wikipedia.org/wiki/MD2:
* >
* > Rogier and Chauvaud (1997) described collisions of MD2's compression function,
* > although they were unable to extend the attack to the full MD2.
* >
* > In 2004, MD2 was shown to be vulnerable to a preimage attack with time
* > complexity equivalent to 2104 applications of the compression function
* > (Muller, 2004).
* > The author concludes, "MD2 can no longer be considered a secure one-way
* > hash function".
*
* also, this implementaton is quite slow.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
public class MD2 implements IHash
{
public static const HASH_SIZE:int = 16;
public var pad_size:int = 48; // probably will never get used, only here for SSL 3.0 support
private static const S:Array = [ // PI Digits
41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, 19,
98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, 76, 130, 202,
30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, 138, 23, 229, 18,
190, 78, 196, 214, 218, 158, 222, 73, 160, 251, 245, 142, 187, 47, 238, 122,
169, 104, 121, 145, 21, 178, 7, 63, 148, 194, 16, 137, 11, 34, 95, 33,
128, 127, 93, 154, 90, 144, 50, 39, 53, 62, 204, 231, 191, 247, 151, 3,
255, 25, 48, 179, 72, 165, 181, 209, 215, 94, 146, 42, 172, 86, 170, 198,
79, 184, 56, 210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241,
69, 157, 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2,
27, 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, 234, 38,
44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, 129, 77, 82,
106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, 8, 12, 189, 177, 74,
120, 136, 149, 139, 227, 99, 232, 109, 233, 203, 213, 254, 59, 0, 29, 57,
242, 239, 183, 14, 102, 88, 208, 228, 166, 119, 114, 248, 235, 117, 75, 10,
49, 68, 80, 180, 143, 237, 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 ];
public function MD2() { }
public function getInputSize():uint
{
return 16;
}
public function getPadSize():int {
return pad_size;
}
public function getHashSize():uint
{
return HASH_SIZE;
}
public function hash(src:ByteArray):ByteArray
{
var savedLength:uint = src.length;
// 3.1 Step 1. Padding
var i:uint = (16-src.length%16) || 16;
do {
src[src.length]=i;
} while (src.length%16!=0);
// 3.2 Step 2. Checksum
var len:uint = src.length;
var checksum:ByteArray = new ByteArray;
var L:uint = 0;
for (i = 0;i<len;i+=16) {
for (var j:uint=0;j<16;j++) {
L = checksum[j] ^= S[src[i+j] ^ L];
}
}
src.position = src.length;
src.writeBytes(checksum);
len += 16;
// 3.3 Step 3. MD Buffer
var X:ByteArray = new ByteArray;
// 3.4 Process Message
for (i=0;i<len;i+=16) {
/* Copy block i into X */
for (j=0;j<16;j++) {
X[32+j] = (X[16+j] = src[i+j])^X[j];
}
var t:uint=0;
/* Do 18 rounds */
for (j=0;j<18;j++) {
/* Round j. */
for (var k:uint=0;k<48;k++) {
X[k] = t = X[k]^S[t];
}
t = (t+j)&0xff;
}
}
// 3.5 Step 5. Output
X.length = 16;
// restore original length;
src.length = savedLength;
return X;
}
public function toString():String
{
return "md2";
}
}
}
@@ -1,204 +0,0 @@
/**
* MD5
*
* An ActionScript 3 implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Copyright (c) 2007 Henri Torgemane
*
* Derived from
* A JavaScript implementation of the same.
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
*
* Note:
* This algorithm should not be your first choice for new developements, but is
* included to allow interoperability with existing codes and protocols.
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
import flash.utils.Endian;
public class MD5 implements IHash
{
public static const HASH_SIZE:int = 16;
public var pad_size:int = 48;
public function MD5() { }
public function getInputSize():uint
{
return 64;
}
public function getHashSize():uint
{
return HASH_SIZE;
}
public function getPadSize():int
{
return pad_size;
}
public function hash(src:ByteArray):ByteArray
{
var len:uint = src.length *8;
var savedEndian:String = src.endian;
// pad to nearest int.
while (src.length%4!=0) {
src[src.length]=0;
}
// convert ByteArray to an array of uint
src.position=0;
var a:Array = [];
src.endian=Endian.LITTLE_ENDIAN
for (var i:uint=0;i<src.length;i+=4) {
a.push(src.readUnsignedInt());
}
var h:Array = core_md5(a, len);
var out:ByteArray = new ByteArray;
out.endian=Endian.LITTLE_ENDIAN;
for (i=0;i<4;i++) {
out.writeUnsignedInt(h[i]);
}
// restore length!
src.length = len/8;
src.endian = savedEndian;
return out;
}
private function core_md5(x:Array, len:uint):Array {
/* append padding */
x[len >> 5] |= 0x80 << ((len) % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;
var a:uint = 0x67452301; // 1732584193;
var b:uint = 0xEFCDAB89; //-271733879;
var c:uint = 0x98BADCFE; //-1732584194;
var d:uint = 0x10325476; // 271733878;
for(var i:uint = 0; i < x.length; i += 16)
{
x[i]||=0; x[i+1]||=0; x[i+2]||=0; x[i+3]||=0;
x[i+4]||=0; x[i+5]||=0; x[i+6]||=0; x[i+7]||=0;
x[i+8]||=0; x[i+9]||=0; x[i+10]||=0; x[i+11]||=0;
x[i+12]||=0; x[i+13]||=0; x[i+14]||=0; x[i+15]||=0;
var olda:uint = a;
var oldb:uint = b;
var oldc:uint = c;
var oldd:uint = d;
a = ff(a, b, c, d, x[i+ 0], 7 , 0xD76AA478);
d = ff(d, a, b, c, x[i+ 1], 12, 0xE8C7B756);
c = ff(c, d, a, b, x[i+ 2], 17, 0x242070DB);
b = ff(b, c, d, a, x[i+ 3], 22, 0xC1BDCEEE);
a = ff(a, b, c, d, x[i+ 4], 7 , 0xF57C0FAF);
d = ff(d, a, b, c, x[i+ 5], 12, 0x4787C62A);
c = ff(c, d, a, b, x[i+ 6], 17, 0xA8304613);
b = ff(b, c, d, a, x[i+ 7], 22, 0xFD469501);
a = ff(a, b, c, d, x[i+ 8], 7 , 0x698098D8);
d = ff(d, a, b, c, x[i+ 9], 12, 0x8B44F7AF);
c = ff(c, d, a, b, x[i+10], 17, 0xFFFF5BB1);
b = ff(b, c, d, a, x[i+11], 22, 0x895CD7BE);
a = ff(a, b, c, d, x[i+12], 7 , 0x6B901122);
d = ff(d, a, b, c, x[i+13], 12, 0xFD987193);
c = ff(c, d, a, b, x[i+14], 17, 0xA679438E);
b = ff(b, c, d, a, x[i+15], 22, 0x49B40821);
a = gg(a, b, c, d, x[i+ 1], 5 , 0xf61e2562);
d = gg(d, a, b, c, x[i+ 6], 9 , 0xc040b340);
c = gg(c, d, a, b, x[i+11], 14, 0x265e5a51);
b = gg(b, c, d, a, x[i+ 0], 20, 0xe9b6c7aa);
a = gg(a, b, c, d, x[i+ 5], 5 , 0xd62f105d);
d = gg(d, a, b, c, x[i+10], 9 , 0x2441453);
c = gg(c, d, a, b, x[i+15], 14, 0xd8a1e681);
b = gg(b, c, d, a, x[i+ 4], 20, 0xe7d3fbc8);
a = gg(a, b, c, d, x[i+ 9], 5 , 0x21e1cde6);
d = gg(d, a, b, c, x[i+14], 9 , 0xc33707d6);
c = gg(c, d, a, b, x[i+ 3], 14, 0xf4d50d87);
b = gg(b, c, d, a, x[i+ 8], 20, 0x455a14ed);
a = gg(a, b, c, d, x[i+13], 5 , 0xa9e3e905);
d = gg(d, a, b, c, x[i+ 2], 9 , 0xfcefa3f8);
c = gg(c, d, a, b, x[i+ 7], 14, 0x676f02d9);
b = gg(b, c, d, a, x[i+12], 20, 0x8d2a4c8a);
a = hh(a, b, c, d, x[i+ 5], 4 , 0xfffa3942);
d = hh(d, a, b, c, x[i+ 8], 11, 0x8771f681);
c = hh(c, d, a, b, x[i+11], 16, 0x6d9d6122);
b = hh(b, c, d, a, x[i+14], 23, 0xfde5380c);
a = hh(a, b, c, d, x[i+ 1], 4 , 0xa4beea44);
d = hh(d, a, b, c, x[i+ 4], 11, 0x4bdecfa9);
c = hh(c, d, a, b, x[i+ 7], 16, 0xf6bb4b60);
b = hh(b, c, d, a, x[i+10], 23, 0xbebfbc70);
a = hh(a, b, c, d, x[i+13], 4 , 0x289b7ec6);
d = hh(d, a, b, c, x[i+ 0], 11, 0xeaa127fa);
c = hh(c, d, a, b, x[i+ 3], 16, 0xd4ef3085);
b = hh(b, c, d, a, x[i+ 6], 23, 0x4881d05);
a = hh(a, b, c, d, x[i+ 9], 4 , 0xd9d4d039);
d = hh(d, a, b, c, x[i+12], 11, 0xe6db99e5);
c = hh(c, d, a, b, x[i+15], 16, 0x1fa27cf8);
b = hh(b, c, d, a, x[i+ 2], 23, 0xc4ac5665);
a = ii(a, b, c, d, x[i+ 0], 6 , 0xf4292244);
d = ii(d, a, b, c, x[i+ 7], 10, 0x432aff97);
c = ii(c, d, a, b, x[i+14], 15, 0xab9423a7);
b = ii(b, c, d, a, x[i+ 5], 21, 0xfc93a039);
a = ii(a, b, c, d, x[i+12], 6 , 0x655b59c3);
d = ii(d, a, b, c, x[i+ 3], 10, 0x8f0ccc92);
c = ii(c, d, a, b, x[i+10], 15, 0xffeff47d);
b = ii(b, c, d, a, x[i+ 1], 21, 0x85845dd1);
a = ii(a, b, c, d, x[i+ 8], 6 , 0x6fa87e4f);
d = ii(d, a, b, c, x[i+15], 10, 0xfe2ce6e0);
c = ii(c, d, a, b, x[i+ 6], 15, 0xa3014314);
b = ii(b, c, d, a, x[i+13], 21, 0x4e0811a1);
a = ii(a, b, c, d, x[i+ 4], 6 , 0xf7537e82);
d = ii(d, a, b, c, x[i+11], 10, 0xbd3af235);
c = ii(c, d, a, b, x[i+ 2], 15, 0x2ad7d2bb);
b = ii(b, c, d, a, x[i+ 9], 21, 0xeb86d391);
a += olda;
b += oldb;
c += oldc;
d += oldd;
}
return [ a, b, c, d ];
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
private function rol(num:uint, cnt:uint):uint
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* These functions implement the four basic operations the algorithm uses.
*/
private function cmn(q:uint, a:uint, b:uint, x:uint, s:uint, t:uint):uint {
return rol(a + q + x + t, s) + b;
}
private function ff(a:uint, b:uint, c:uint, d:uint, x:uint, s:uint, t:uint):uint {
return cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
private function gg(a:uint, b:uint, c:uint, d:uint, x:uint, s:uint, t:uint):uint {
return cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
private function hh(a:uint, b:uint, c:uint, d:uint, x:uint, s:uint, t:uint):uint {
return cmn(b ^ c ^ d, a, b, x, s, t);
}
private function ii(a:uint, b:uint, c:uint, d:uint, x:uint, s:uint, t:uint):uint {
return cmn(c ^ (b | (~d)), a, b, x, s, t);
}
public function toString():String {
return "md5";
}
}
}
@@ -1,106 +0,0 @@
/**
* SHA1
*
* An ActionScript 3 implementation of Secure Hash Algorithm, SHA-1, as defined
* in FIPS PUB 180-1
* Copyright (c) 2007 Henri Torgemane
*
* Derived from:
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
* in FIPS PUB 180-1
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
public class SHA1 extends SHABase implements IHash
{
public static const HASH_SIZE:int = 20;
public override function getHashSize():uint {
return HASH_SIZE;
}
protected override function core(x:Array, len:uint):Array
{
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w:Array = [];
var a:uint = 0x67452301; //1732584193;
var b:uint = 0xEFCDAB89; //-271733879;
var c:uint = 0x98BADCFE; //-1732584194;
var d:uint = 0x10325476; //271733878;
var e:uint = 0xC3D2E1F0; //-1009589776;
for(var i:uint = 0; i < x.length; i += 16)
{
var olda:uint = a;
var oldb:uint = b;
var oldc:uint = c;
var oldd:uint = d;
var olde:uint = e;
for(var j:uint = 0; j < 80; j++)
{
if (j < 16) {
w[j] = x[i + j] || 0;
} else {
w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
}
var t:uint = rol(a,5) + ft(j,b,c,d) + e + w[j] + kt(j);
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a += olda;
b += oldb;
c += oldc;
d += oldd;
e += olde;
}
return [ a, b, c, d, e ];
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
private function rol(num:uint, cnt:uint):uint
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
private function ft(t:uint, b:uint, c:uint, d:uint):uint
{
if(t < 20) return (b & c) | ((~b) & d);
if(t < 40) return b ^ c ^ d;
if(t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
private function kt(t:uint):uint
{
return (t < 20) ? 0x5A827999 : (t < 40) ? 0x6ED9EBA1 :
(t < 60) ? 0x8F1BBCDC : 0xCA62C1D6;
}
public override function toString():String {
return "sha1";
}
}
}
@@ -1,28 +0,0 @@
/**
* SHA224
*
* An ActionScript 3 implementation of Secure Hash Algorithm, SHA-224, as defined
* in FIPS PUB 180-2
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
public class SHA224 extends SHA256
{
function SHA224() {
h = [
0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
];
}
public override function getHashSize():uint {
return 28;
}
public override function toString():String {
return "sha224";
}
}
}
@@ -1,115 +0,0 @@
/**
* SHA256
*
* An ActionScript 3 implementation of Secure Hash Algorithm, SHA-256, as defined
* in FIPS PUB 180-2
* Copyright (c) 2007 Henri Torgemane
*
* Derived from:
* A JavaScript implementation of the Secure Hash Standard
* Version 0.3 Copyright Angel Marin 2003-2004 - http://anmar.eu.org/
* Derived from:
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
* in FIPS PUB 180-1
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
public class SHA256 extends SHABase implements IHash
{
protected static const k:Array = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2];
protected var h:Array = [
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
];
public function SHA256(){
}
public override function getHashSize():uint
{
return 32;
}
protected override function core(x:Array, len:uint):Array {
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w:Array = [];
var a:uint = h[0];
var b:uint = h[1];
var c:uint = h[2];
var d:uint = h[3];
var e:uint = h[4];
var f:uint = h[5];
var g:uint = h[6];
var h:uint = h[7];
for (var i:uint=0; i<x.length; i+=16) {
var olda:uint = a;
var oldb:uint = b;
var oldc:uint = c;
var oldd:uint = d;
var olde:uint = e;
var oldf:uint = f;
var oldg:uint = g;
var oldh:uint = h;
for (var j:uint=0; j<64; j++) {
if (j<16) {
w[j] = x[i+j] || 0;
} else {
var s0:uint = rrol(w[j-15],7)^rrol(w[j-15],18)^(w[j-15]>>>3);
var s1:uint = rrol(w[j-2], 17)^rrol(w[j-2],19)^(w[j-2]>>>10);
w[j] = w[j-16] + s0 + w[j-7] + s1;
}
var t2:uint = (rrol(a,2) ^ rrol(a,13) ^ rrol(a,22)) + ((a&b) ^ (a&c) ^ (b&c));
var t1:uint = h + (rrol(e,6) ^ rrol(e,11) ^ rrol(e,25)) + ((e&f)^(g&~e)) + k[j] + w[j]
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
a += olda;
b += oldb;
c += oldc;
d += oldd;
e += olde;
f += oldf;
g += oldg;
h += oldh;
}
return [ a,b,c,d,e,f,g,h ];
}
/*
* Bitwise rotate a 32-bit number to the right.
*/
protected function rrol(num:uint, cnt:uint):uint {
return (num << (32-cnt)) | (num >>> cnt);
}
public override function toString():String {
return "sha256";
}
}
}
@@ -1,71 +0,0 @@
/**
* SHABase
*
* An ActionScript 3 abstract class for the SHA family of hash functions
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
import flash.utils.Endian;
public class SHABase implements IHash
{
public function SHABase() { }
public var pad_size:int = 40;
public function getInputSize():uint
{
return 64;
}
public function getHashSize():uint
{
return 0;
}
public function getPadSize():int
{
return pad_size;
}
public function hash(src:ByteArray):ByteArray
{
var savedLength:uint = src.length;
var savedEndian:String = src.endian;
src.endian = Endian.BIG_ENDIAN;
var len:uint = savedLength *8;
// pad to nearest int.
while (src.length%4!=0) {
src[src.length]=0;
}
// convert ByteArray to an array of uint
src.position=0;
var a:Array = [];
for (var i:uint=0;i<src.length;i+=4) {
a.push(src.readUnsignedInt());
}
var h:Array = core(a, len);
var out:ByteArray = new ByteArray;
var words:uint = getHashSize()/4;
for (i=0;i<words;i++) {
out.writeUnsignedInt(h[i]);
}
// unpad, to leave the source untouched.
src.length = savedLength;
src.endian = savedEndian;
return out;
}
protected function core(x:Array, len:uint):Array {
return null;
}
public function toString():String {
return "sha";
}
}
}
@@ -1,90 +0,0 @@
/**
* ARC4
*
* An ActionScript 3 implementation of RC4
* Copyright (c) 2007 Henri Torgemane
*
* Derived from:
* The jsbn library, Copyright (c) 2003-2005 Tom Wu
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.prng
{
import com.hurlant.crypto.symmetric.IStreamCipher;
import com.hurlant.util.Memory;
import flash.utils.ByteArray;
public class ARC4 implements IPRNG, IStreamCipher {
private var i:int = 0;
private var j:int = 0;
private var S:ByteArray;
private const psize:uint = 256;
public function ARC4(key:ByteArray = null){
S = new ByteArray;
if (key) {
init(key);
}
}
public function getPoolSize():uint {
return psize;
}
public function init(key:ByteArray):void {
var i:int;
var j:int;
var t:int;
for (i=0; i<256; ++i) {
S[i] = i;
}
j=0;
for (i=0; i<256; ++i) {
j = (j + S[i] + key[i%key.length]) & 255;
t = S[i];
S[i] = S[j];
S[j] = t;
}
this.i=0;
this.j=0;
}
public function next():uint {
var t:int;
i = (i+1)&255;
j = (j+S[i])&255;
t = S[i];
S[i] = S[j];
S[j] = t;
return S[(t+S[i])&255];
}
public function getBlockSize():uint {
return 1;
}
public function encrypt(block:ByteArray):void {
var i:uint = 0;
while (i<block.length) {
block[i++] ^= next();
}
}
public function decrypt(block:ByteArray):void {
encrypt(block); // the beauty of XOR.
}
public function dispose():void {
var i:uint = 0;
if (S!=null) {
for (i=0;i<S.length;i++) {
S[i] = Math.random()*256;
}
S.length=0;
S = null;
}
this.i = 0;
this.j = 0;
Memory.gc();
}
public function toString():String {
return "rc4";
}
}
}
@@ -1,20 +0,0 @@
/**
* IPRNG
*
* An interface for classes that can be used a pseudo-random number generators
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.prng
{
import flash.utils.ByteArray;
public interface IPRNG {
function getPoolSize():uint;
function init(key:ByteArray):void;
function next():uint;
function dispose():void;
function toString():String;
}
}
@@ -1,119 +0,0 @@
/**
* Random
*
* An ActionScript 3 implementation of a Random Number Generator
* Copyright (c) 2007 Henri Torgemane
*
* Derived from:
* The jsbn library, Copyright (c) 2003-2005 Tom Wu
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.prng
{
import flash.utils.ByteArray;
import com.hurlant.util.Memory;
import flash.system.System;
import flash.system.Capabilities;
import flash.accessibility.AccessibilityProperties;
import flash.display.SWFVersion;
import flash.display.Stage;
import flash.utils.getTimer;
import flash.text.Font;
public class Random
{
private var state:IPRNG;
private var ready:Boolean = false;
private var pool:ByteArray;
private var psize:int;
private var pptr:int;
private var seeded:Boolean = false;
public function Random(prng:Class = null) {
if (prng==null) prng = ARC4;
state = new prng as IPRNG;
psize= state.getPoolSize();
pool = new ByteArray;
pptr = 0;
while (pptr <psize) {
var t:uint = 65536*Math.random();
pool[pptr++] = t >>> 8;
pool[pptr++] = t&255;
}
pptr=0;
seed();
}
public function seed(x:int = 0):void {
if (x==0) {
x = new Date().getTime();
}
pool[pptr++] ^= x & 255;
pool[pptr++] ^= (x>>8)&255;
pool[pptr++] ^= (x>>16)&255;
pool[pptr++] ^= (x>>24)&255;
pptr %= psize;
seeded = true;
}
/**
* Gather anything we have that isn't entirely predictable:
* - memory used
* - system capabilities
* - timing stuff
* - installed fonts
*/
public function autoSeed():void {
var b:ByteArray = new ByteArray;
b.writeUnsignedInt(System.totalMemory);
b.writeUTF(Capabilities.serverString);
b.writeUnsignedInt(getTimer());
b.writeUnsignedInt((new Date).getTime());
var a:Array = Font.enumerateFonts(true);
for each (var f:Font in a) {
b.writeUTF(f.fontName);
b.writeUTF(f.fontStyle);
b.writeUTF(f.fontType);
}
b.position=0;
while (b.bytesAvailable>=4) {
seed(b.readUnsignedInt());
}
}
public function nextBytes(buffer:ByteArray, length:int):void {
while (length--) {
buffer.writeByte(nextByte());
}
}
public function nextByte():int {
if (!ready) {
if (!seeded) {
autoSeed();
}
state.init(pool);
pool.length = 0;
pptr = 0;
ready = true;
}
return state.next();
}
public function dispose():void {
for (var i:uint=0;i<pool.length;i++) {
pool[i] = Math.random()*256;
}
pool.length=0;
pool = null;
state.dispose();
state = null;
psize = 0;
pptr = 0;
Memory.gc();
}
public function toString():String {
return "random-"+state.toString();
}
}
}
@@ -1,142 +0,0 @@
/**
* TLSPRF
*
* An ActionScript 3 implementation of a pseudo-random generator
* that follows the TLS specification
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.prng
{
import flash.utils.ByteArray;
import com.hurlant.crypto.hash.HMAC;
import com.hurlant.crypto.hash.MD5;
import com.hurlant.crypto.hash.SHA1;
import com.hurlant.util.Memory;
import com.hurlant.util.Hex;
import flash.utils.IDataOutput;
/**
* There's "Random", and then there's TLS Random.
* .
* Still Pseudo-random, though.
*/
public class TLSPRF
{
// XXX WAY TOO MANY STRUCTURES HERE
// seed
private var seed:ByteArray;
// P_MD5's secret
private var s1:ByteArray;
// P_SHA-1's secret
private var s2:ByteArray;
// HMAC_MD5's A
private var a1:ByteArray;
// HMAC_SHA1's A
private var a2:ByteArray;
// Pool for P_MD5
private var p1:ByteArray;
// Pool for P_SHA1
private var p2:ByteArray;
// Data for HMAC_MD5
private var d1:ByteArray;
// Data for HMAC_SHA1
private var d2:ByteArray;
private var hmac_md5:HMAC;
private var hmac_sha1:HMAC;
public function TLSPRF(secret:ByteArray, label:String, seed:ByteArray) {
var l:int = Math.ceil(secret.length/2);
var s1:ByteArray = new ByteArray;
var s2:ByteArray = new ByteArray;
s1.writeBytes(secret, 0, l);
s2.writeBytes(secret, secret.length-l, l);
var s:ByteArray = new ByteArray;
s.writeUTFBytes(label);
s.writeBytes(seed);
this.seed = s;
this.s1 = s1;
this.s2 = s2;
hmac_md5 = new HMAC(new MD5);
hmac_sha1 = new HMAC(new SHA1);
this.a1 = hmac_md5.compute(s1, this.seed);
this.a2 = hmac_sha1.compute(s2, this.seed);
p1 = new ByteArray;
p2 = new ByteArray;
d1 = new ByteArray;
d2 = new ByteArray;
d1.position = MD5.HASH_SIZE;
d1.writeBytes(this.seed);
d2.position = SHA1.HASH_SIZE;
d2.writeBytes(this.seed);
}
// XXX HORRIBLY SLOW. REWRITE.
public function nextBytes(buffer:IDataOutput, length:int):void {
while (length--) {
buffer.writeByte(nextByte());
}
}
public function nextByte():int {
if (p1.bytesAvailable==0) {
more_md5();
}
if (p2.bytesAvailable==0) {
more_sha1();
}
return p1.readUnsignedByte()^p2.readUnsignedByte();
}
public function dispose():void {
seed = dba(seed);
s1 = dba(s1);
s2 = dba(s2);
a1 = dba(a1);
a2 = dba(a2);
p1 = dba(p1);
p2 = dba(p2);
d1 = dba(d1);
d2 = dba(d2);
hmac_md5.dispose();
hmac_md5 = null;
hmac_sha1.dispose();
hmac_sha1 = null;
Memory.gc();
}
public function toString():String {
return "tls-prf";
}
private function dba(ba:ByteArray):ByteArray {
for (var i:uint=0;i<ba.length;i++) {
ba[i]=0;
}
ba.length=0;
return null;
}
private function more_md5():void {
d1.position=0;
d1.writeBytes(a1);
var p:int = p1.position;
var more:ByteArray = hmac_md5.compute(s1, d1);
a1 = hmac_md5.compute(s1, a1);
p1.writeBytes(more);
p1.position=p;
}
private function more_sha1():void {
d2.position=0;
d2.writeBytes(a2);
var p:int = p2.position;
var more:ByteArray = hmac_sha1.compute(s2, d2);
a2 = hmac_sha1.compute(s2, a2);
p2.writeBytes(more);
p2.position=p;
}
}
}
@@ -1,339 +0,0 @@
/**
* RSAKey
*
* An ActionScript 3 implementation of RSA + PKCS#1 (light version)
* Copyright (c) 2007 Henri Torgemane
*
* Derived from:
* The jsbn library, Copyright (c) 2003-2005 Tom Wu
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.rsa
{
import com.hurlant.crypto.prng.Random;
import com.hurlant.math.BigInteger;
import com.hurlant.util.Memory;
import flash.utils.ByteArray;
import com.hurlant.crypto.hash.IHash;
import com.hurlant.util.Hex;
import com.hurlant.util.der.DER;
import com.hurlant.util.der.OID;
import com.hurlant.util.ArrayUtil;
import com.hurlant.util.der.Type;
import com.hurlant.util.der.Sequence;
import com.hurlant.util.der.ObjectIdentifier;
import com.hurlant.util.der.ByteString;
import com.hurlant.crypto.tls.TLSError;
/**
* Current limitations:
* exponent must be smaller than 2^31.
*/
public class RSAKey
{
// public key
public var e:int; // public exponent. must be <2^31
public var n:BigInteger; // modulus
// private key
public var d:BigInteger;
// extended private key
public var p:BigInteger;
public var q:BigInteger;
public var dmp1:BigInteger
public var dmq1:BigInteger;
public var coeff:BigInteger;
// flags. flags are cool.
protected var canDecrypt:Boolean;
protected var canEncrypt:Boolean;
public function RSAKey(N:BigInteger, E:int,
D:BigInteger=null,
P:BigInteger = null, Q:BigInteger=null,
DP:BigInteger=null, DQ:BigInteger=null,
C:BigInteger=null) {
this.n = N;
this.e = E;
this.d = D;
this.p = P;
this.q = Q;
this.dmp1 = DP;
this.dmq1 = DQ;
this.coeff = C;
// adjust a few flags.
canEncrypt = (n!=null&&e!=0);
canDecrypt = (canEncrypt&&d!=null);
}
public static function parsePublicKey(N:String, E:String):RSAKey {
return new RSAKey(new BigInteger(N, 16, true), parseInt(E,16));
}
public static function parsePrivateKey(N:String, E:String, D:String,
P:String=null,Q:String=null, DMP1:String=null, DMQ1:String=null, IQMP:String=null):RSAKey {
if (P==null) {
return new RSAKey(new BigInteger(N,16, true), parseInt(E,16), new BigInteger(D,16, true));
} else {
return new RSAKey(new BigInteger(N,16, true), parseInt(E,16), new BigInteger(D,16, true),
new BigInteger(P,16, true), new BigInteger(Q,16, true),
new BigInteger(DMP1,16, true), new BigInteger(DMQ1, 16, true),
new BigInteger(IQMP, 16, true));
}
}
public function getBlockSize():uint {
return (n.bitLength()+7)/8;
}
public function dispose():void {
e = 0;
n.dispose();
n = null;
Memory.gc();
}
public function encrypt(src:ByteArray, dst:ByteArray, length:uint, pad:Function=null):void {
_encrypt(doPublic, src, dst, length, pad, 0x02);
}
public function decrypt(src:ByteArray, dst:ByteArray, length:uint, pad:Function=null):void {
_decrypt(doPrivate2, src, dst, length, pad, 0x02);
}
public function sign(src:ByteArray, dst:ByteArray, length:uint, pad:Function = null):void {
_encrypt(doPrivate2, src, dst, length, pad, 0x01);
}
public function verify(src:ByteArray, dst:ByteArray, length:uint, pad:Function = null):void {
_decrypt(doPublic, src, dst, length, pad, 0x01);
}
private function _encrypt(op:Function, src:ByteArray, dst:ByteArray, length:uint, pad:Function, padType:int):void {
// adjust pad if needed
if (pad==null) pad = pkcs1pad;
// convert src to BigInteger
if (src.position >= src.length) {
src.position = 0;
}
var bl:uint = getBlockSize();
var end:int = src.position + length;
while (src.position<end) {
var block:BigInteger = new BigInteger(pad(src, end, bl, padType), bl, true);
var chunk:BigInteger = op(block);
chunk.toArray(dst);
}
}
private function _decrypt(op:Function, src:ByteArray, dst:ByteArray, length:uint, pad:Function, padType:int):void {
// adjust pad if needed
if (pad==null) pad = pkcs1unpad;
// convert src to BigInteger
if (src.position >= src.length) {
src.position = 0;
}
var bl:uint = getBlockSize();
var end:int = src.position + length;
while (src.position<end) {
var block:BigInteger = new BigInteger(src, bl, true);
var chunk:BigInteger = op(block);
var b:ByteArray = pad(chunk, bl, padType);
if (b == null)
throw new TLSError( "Decrypt error - padding function returned null!", TLSError.decode_error );
// if (b != null)
dst.writeBytes(b);
}
}
/**
* PKCS#1 pad. type 1 (0xff) or 2, random.
* puts as much data from src into it, leaves what doesn't fit alone.
*/
private function pkcs1pad(src:ByteArray, end:int, n:uint, type:uint = 0x02):ByteArray {
var out:ByteArray = new ByteArray;
var p:uint = src.position;
end = Math.min(end, src.length, p+n-11);
src.position = end;
var i:int = end-1;
while (i>=p && n>11) {
out[--n] = src[i--];
}
out[--n] = 0;
if (type==0x02) { // type 2
var rng:Random = new Random;
var x:int = 0;
while (n>2) {
do {
x = rng.nextByte();
} while (x==0);
out[--n] = x;
}
} else { // type 1
while (n>2) {
out[--n] = 0xFF;
}
}
out[--n] = type;
out[--n] = 0;
return out;
}
/**
*
* @param src
* @param n
* @param type Not used.
* @return
*
*/
private function pkcs1unpad(src:BigInteger, n:uint, type:uint = 0x02):ByteArray {
var b:ByteArray = src.toByteArray();
var out:ByteArray = new ByteArray;
b.position = 0;
var i:int = 0;
while (i<b.length && b[i]==0) ++i;
if (b.length-i != n-1 || b[i]!=type) {
trace("PKCS#1 unpad: i="+i+", expected b[i]=="+type+", got b[i]="+b[i].toString(16));
return null;
}
++i;
while (b[i]!=0) {
if (++i>=b.length) {
trace("PKCS#1 unpad: i="+i+", b[i-1]!=0 (="+b[i-1].toString(16)+")");
return null;
}
}
while (++i < b.length) {
out.writeByte(b[i]);
}
out.position = 0;
return out;
}
/**
* Raw pad.
*/
public function rawpad(src:ByteArray, end:int, n:uint, type:uint = 0):ByteArray {
return src;
}
public function rawunpad(src:BigInteger, n:uint, type:uint = 0):ByteArray {
return src.toByteArray();
}
public function toString():String {
return "rsa";
}
public function dump():String {
var s:String= "N="+n.toString(16)+"\n"+
"E="+e.toString(16)+"\n";
if (canDecrypt) {
s+="D="+d.toString(16)+"\n";
if (p!=null && q!=null) {
s+="P="+p.toString(16)+"\n";
s+="Q="+q.toString(16)+"\n";
s+="DMP1="+dmp1.toString(16)+"\n";
s+="DMQ1="+dmq1.toString(16)+"\n";
s+="IQMP="+coeff.toString(16)+"\n";
}
}
return s;
}
/**
*
* note: We should have a "nice" variant of this function that takes a callback,
* and perform the computation is small fragments, to keep the web browser
* usable.
*
* @param B
* @param E
* @return a new random private key B bits long, using public expt E
*
*/
public static function generate(B:uint, E:String):RSAKey {
var rng:Random = new Random;
var qs:uint = B>>1;
var key:RSAKey = new RSAKey(null,0,null);
key.e = parseInt(E, 16);
var ee:BigInteger = new BigInteger(E,16, true);
for (;;) {
for (;;) {
key.p = bigRandom(B-qs, rng);
if (key.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE)==0 &&
key.p.isProbablePrime(10)) break;
}
for (;;) {
key.q = bigRandom(qs, rng);
if (key.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE)==0 &&
key.q.isProbablePrime(10)) break;
}
if (key.p.compareTo(key.q)<=0) {
var t:BigInteger = key.p;
key.p = key.q;
key.q = t;
}
var p1:BigInteger = key.p.subtract(BigInteger.ONE);
var q1:BigInteger = key.q.subtract(BigInteger.ONE);
var phi:BigInteger = p1.multiply(q1);
if (phi.gcd(ee).compareTo(BigInteger.ONE)==0) {
key.n = key.p.multiply(key.q);
key.d = ee.modInverse(phi);
key.dmp1 = key.d.mod(p1);
key.dmq1 = key.d.mod(q1);
key.coeff = key.q.modInverse(key.p);
break;
}
}
return key;
}
protected static function bigRandom(bits:int, rnd:Random):BigInteger {
if (bits<2) return BigInteger.nbv(1);
var x:ByteArray = new ByteArray;
rnd.nextBytes(x, (bits>>3));
x.position = 0;
var b:BigInteger = new BigInteger(x,0,true);
b.primify(bits, 1);
return b;
}
protected function doPublic(x:BigInteger):BigInteger {
return x.modPowInt(e, n);
}
protected function doPrivate2(x:BigInteger):BigInteger {
if (p==null && q==null) {
return x.modPow(d,n);
}
var xp:BigInteger = x.mod(p).modPow(dmp1, p);
var xq:BigInteger = x.mod(q).modPow(dmq1, q);
while (xp.compareTo(xq)<0) {
xp = xp.add(p);
}
var r:BigInteger = xp.subtract(xq).multiply(coeff).mod(p).multiply(q).add(xq);
return r;
}
protected function doPrivate(x:BigInteger):BigInteger {
if (p==null || q==null) {
return x.modPow(d, n);
}
// TODO: re-calculate any missing CRT params
var xp:BigInteger = x.mod(p).modPow(dmp1, p);
var xq:BigInteger = x.mod(q).modPow(dmq1, q);
while (xp.compareTo(xq)<0) {
xp = xp.add(p);
}
return xp.subtract(xq).multiply(coeff).mod(p).multiply(q).add(xq);
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,375 +0,0 @@
/**
* BlowFishKey
*
* An Actionscript 3 implementation of the BlowFish encryption algorithm,
* as documented at http://www.schneier.com/blowfish.html
* Copyright (c) 2007 Henri Torgemane
*
* Derived from:
* The Bouncy Castle Crypto package,
* Copyright (c) 2000-2004 The Legion Of The Bouncy Castle
* (http://www.bouncycastle.org)
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
import com.hurlant.util.Memory;
public class BlowFishKey implements ISymmetricKey
{
private static const KP:Array = [ 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, 0xA4093822, 0x299F31D0,
0x082EFA98, 0xEC4E6C89, 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5,
0xB5470917, 0x9216D5D9, 0x8979FB1B ];
private static const KS0:Array = [ 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, 0x24A19947,
0xB3916CF7, 0x0801F2E2, 0x858EFC16, 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, 0x0D95748F, 0x728EB658,
0x718BCD58, 0x82154AEE, 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, 0xC5D1B023, 0x286085F0, 0xCA417918,
0xB8DB38EF, 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60,
0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, 0xA15486AF,
0x7C72E993, 0xB3EE1411, 0x636FBC2A, 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, 0xAFD6BA33, 0x6C24CF5C,
0x7A325381, 0x28958677, 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, 0x61D809CC, 0xFB21A991, 0x487CAC60,
0x5DEC8032, 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239,
0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0, 0x6A51A0D2,
0xD8542F68, 0x960FA728, 0xAB5133A3, 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, 0xA1F1651D, 0x39AF0176,
0x66CA593E, 0x82430E88, 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, 0xE06F75D8, 0x85C12073, 0x401A449F,
0x56C16AA6, 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B,
0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, 0xC1A94FB6,
0x409F60C4, 0x5E5C9EC2, 0x196A2463, 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, 0x6DFC511F, 0x9B30952C,
0xCC814544, 0xAF5EBD09, 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, 0xC0CBA857, 0x45C8740F, 0xD20B5F39,
0xB9D3FBDB, 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, 0x9E5C57BB,
0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, 0x695B27B0, 0xBBCA58C8,
0xE1FFA35D, 0xB8F011A0, 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, 0x9A53E479, 0xB6F84565, 0xD28E49BC,
0x4BFB9790, 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8, 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4,
0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, 0x8FF6E2FB,
0xF2122B64, 0x8888B812, 0x900DF01C, 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, 0x2F2F2218, 0xBE0E1777,
0xEA752DFE, 0x8B021FA1, 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81,
0xD2ADA8D9, 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF,
0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF, 0x2464369B,
0xF009B91E, 0x5563911D, 0x59DFA6AA, 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, 0x83260376, 0x6295CFA9,
0x11C81968, 0x4E734A41, 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915, 0xD60F573F, 0xBC9BC6E4, 0x2B60A476,
0x81E67400, 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A ];
private static const KS1:Array = [ 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, 0xECAA8C71,
0x699A17FF, 0x5664526C, 0xC2B19EE1, 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, 0x3F54989A, 0x5B429D65,
0x6B8FE4D6, 0x99F73FD6, 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, 0x4CDD2086, 0x8470EB26, 0x6382E9C6,
0x021ECC5E, 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1, 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737,
0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, 0xAE0CF51A,
0x3CB574B2, 0x25837A58, 0xDC0921BD, 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, 0x3AE5E581, 0x37C2DADC,
0xC8B57634, 0x9AF3DDA7, 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1,
0x183EB331, 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF,
0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, 0x7A584718,
0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, 0xEF1C1847, 0x3215D908,
0xDD433B37, 0x24C2BA16, 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, 0x71DFF89E, 0x10314E55, 0x81AC77D6,
0x5F11199B, 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E,
0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, 0x803E89D6,
0x5266C825, 0x2E4CC978, 0x9C10B36A, 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, 0xF2F74EA7, 0x361D2B3D,
0x1939260F, 0x19C27960, 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, 0xE3BC4595, 0xA67BC883, 0xB17F37D1,
0x018CFF28, 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84,
0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, 0xB5735C90,
0x4C70A239, 0xD59E9E0B, 0xCBAADE14, 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, 0x648B1EAF, 0x19BDF0CA,
0xA02369B9, 0x655ABB50, 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, 0x9B540B19, 0x875FA099, 0x95F7997E,
0x623D7DA8, 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281, 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99,
0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, 0x58EBF2EF,
0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, 0x45EEE2B6, 0xA3AAABEA,
0xDB6C4F15, 0xFACB4FD0, 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, 0xD81E799E, 0x86854DC7, 0xE44B476A,
0x3D816250, 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3, 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285,
0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, 0x3372F092,
0x8D937E41, 0xD65FECF1, 0x6C223BDB, 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, 0xA6078084, 0x19F8509E,
0xE8EFD855, 0x61D99735, 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC, 0x9E447A2E, 0xC3453484, 0xFDD56705,
0x0E1E9EC9, 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340, 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7 ];
private static const KS2:Array = [ 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, 0xD4082471,
0x3320F46A, 0x43B7D4B7, 0x500061AF, 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, 0x4D95FC1D, 0x96B591AF,
0x70F4DDD3, 0x66A02F45, 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, 0x96EB27B3, 0x55FD3941, 0xDA2547E6,
0xABCA0A9A, 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE,
0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, 0x20FE9E35,
0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, 0x3A6EFA74, 0xDD5B4332,
0x6841E7F7, 0xCA7820FB, 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, 0x55533A3A, 0x20838D87, 0xFE6BA9B7,
0xD096954B, 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C,
0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, 0x07F9C9EE,
0x41041F0F, 0x404779A4, 0x5D886E17, 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, 0x257B7834, 0x602A9C60,
0xDFF8E8A3, 0x1F636C1B, 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, 0x6B2395E0, 0x333E92E1, 0x3B240B62,
0xEEBEB922, 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0,
0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, 0xA812DC60,
0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, 0xF1290DC7, 0xCC00FFA3,
0xB5390F92, 0x690FED0B, 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, 0xBB132F88, 0x515BAD24, 0x7B9479BF,
0x763BD6EB, 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C,
0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, 0x44421659,
0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, 0x9DBC8057, 0xF0F7C086,
0x60787BF8, 0x6003604D, 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, 0x83426B33, 0xF01EAB71, 0xB0804187,
0x3C005E5F, 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2,
0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, 0x466E598E,
0x20B45770, 0x8CD55591, 0xC902DE4C, 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, 0xB77F19B6, 0xE0A9DC09,
0x662D09A1, 0xC4324633, 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F,
0x2868F169, 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027,
0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, 0x11E69ED7,
0x2338EA63, 0x53C2DD94, 0xC2C21634, 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, 0x6F05E409, 0x4B7C0188,
0x39720A3D, 0x7C927C24, 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC, 0xED545578, 0x08FCA5B5, 0xD83D7CD3,
0x4DAD0FC4, 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0 ];
private static const KS3:Array = [ 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, 0xD5118E9D,
0xBF0F7315, 0xD62D1C7E, 0xC700C47B, 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, 0x5748AB2F, 0xBC946E79,
0xC6A376D2, 0x6549C2C8, 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, 0x2939BBDB, 0xA9BA4650, 0xAC9526E8,
0xBE5EE304, 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22, 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4,
0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, 0xC72FEFD3,
0xF752F7DA, 0x3F046F69, 0x77FA0A59, 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, 0xE990FD5A, 0x9E34D797,
0x2CF0B7D9, 0x022B8B51, 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472,
0x5A88F54C, 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28,
0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD, 0xC3EB9E15,
0x3C9057A2, 0x97271AEC, 0xA93A072A, 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, 0x7533D928, 0xB155FDF5,
0x03563482, 0x8ABA3CBB, 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F, 0x4DE81751, 0x3830DC8E, 0x379D5862,
0x9320F991, 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680,
0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, 0x5BBEF7DD,
0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, 0x72EACEA8, 0xFA6484BB,
0x8D6612AE, 0xBF3C6F47, 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, 0x740E0D8D, 0xE75B1357, 0xF8721671,
0xAF537D5D, 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, 0xA08839E1,
0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, 0x1A908749, 0xD44FBD9A,
0xD0DADECB, 0xD50ADA38, 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF,
0x27D9459C, 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525, 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1,
0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, 0x9F1F9532,
0xE0D392DF, 0xD3A0342B, 0x8971F21E, 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, 0xDF359F8D, 0x9B992F2E,
0xE60B6F47, 0x0FE3F11D, 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F, 0x1618B166, 0xFD2C1D05, 0x848FD2C5,
0xF6FB2299, 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02, 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC,
0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, 0xC9AA53FD,
0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, 0x53113EC0, 0x1640E3D3,
0x38ABBD60, 0x2547ADF0, 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060, 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0,
0x4CF9AA7E, 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6 ];
// ====================================
// Useful constants
// ====================================
private static const ROUNDS:uint = 16;
private static const BLOCK_SIZE:uint = 8; // bytes = 64 bits
private static const SBOX_SK:uint = 256;
private static const P_SZ:uint = ROUNDS + 2;
private var S0:Array;
private var S1:Array;
private var S2:Array;
private var S3:Array; // the s-boxes
private var P:Array; // the p-array
private var key:ByteArray = null;
public function BlowFishKey(key:ByteArray) {
this.key = key;
setKey(key);
}
public function getBlockSize():uint
{
return BLOCK_SIZE;
}
public function decrypt(block:ByteArray, index:uint=0):void
{
decryptBlock(block, index, block, index);
}
public function dispose():void
{
var i:uint=0;
for (i=0;i<S0.length;i++) { S0[i]=0; }
for (i=0;i<S1.length;i++) { S1[i]=0; }
for (i=0;i<S2.length;i++) { S2[i]=0; }
for (i=0;i<S3.length;i++) { S3[i]=0; }
for (i=0;i<P.length;i++) { P[i]=0; }
S0 = null;
S1 = null;
S2 = null;
S3 = null;
P = null;
for (i=0;i<key.length;i++) {
key[i]=0;
}
key.length = 0;
key = null;
Memory.gc();
}
public function encrypt(block:ByteArray, index:uint=0):void
{
encryptBlock(block, index, block, index);
}
// ==================================
// Private Implementation
// ==================================
private function F(x:uint):uint
{
return (((S0[(x >>> 24)] + S1[(x >>> 16) & 0xff]) ^ S2[(x >>> 8) & 0xff]) + S3[x & 0xff]);
}
/**
* apply the encryption cycle to each value pair in the table.
*/
private function processTable(xl:uint, xr:uint, table:Array):void
{
var size:uint = table.length;
for (var s:uint = 0; s < size; s += 2)
{
xl ^= P[0];
for (var i:uint = 1; i < ROUNDS; i += 2)
{
xr ^= F(xl) ^ P[i];
xl ^= F(xr) ^ P[i + 1];
}
xr ^= P[ROUNDS + 1];
table[s] = xr;
table[s + 1] = xl;
xr = xl; // end of cycle swap
xl = table[s];
}
}
private function setKey(key:ByteArray):void
{
/*
* - comments are from _Applied Crypto_, Schneier, p338 please be
* careful comparing the two, AC numbers the arrays from 1, the enclosed
* code from 0.
*
* (1) Initialise the S-boxes and the P-array, with a fixed string This
* string contains the hexadecimal digits of pi (3.141...)
*/
S0 = KS0.concat();
S1 = KS1.concat();
S2 = KS2.concat();
S3 = KS3.concat();
P = KP.concat();
/*
* (2) Now, XOR P[0] with the first 32 bits of the key, XOR P[1] with
* the second 32-bits of the key, and so on for all bits of the key (up
* to P[17]). Repeatedly cycle through the key bits until the entire
* P-array has been XOR-ed with the key bits
*/
var keyLength:uint= key.length;
var keyIndex:uint = 0;
for (var i:uint = 0; i < P_SZ; i++)
{
// get the 32 bits of the key, in 4 * 8 bit chunks
var data:uint = 0x0000000;
for (var j:uint = 0; j < 4; j++)
{
// create a 32 bit block
data = (data << 8) | (key[keyIndex++] & 0xff);
// wrap when we get to the end of the key
if (keyIndex >= keyLength)
{
keyIndex = 0;
}
}
// XOR the newly created 32 bit chunk onto the P-array
P[i] ^= data;
}
/*
* (3) Encrypt the all-zero string with the Blowfish algorithm, using
* the subkeys described in (1) and (2)
*
* (4) Replace P1 and P2 with the output of step (3)
*
* (5) Encrypt the output of step(3) using the Blowfish algorithm, with
* the modified subkeys.
*
* (6) Replace P3 and P4 with the output of step (5)
*
* (7) Continue the process, replacing all elements of the P-array and
* then all four S-boxes in order, with the output of the continuously
* changing Blowfish algorithm
*/
processTable(0, 0, P);
processTable(P[P_SZ - 2], P[P_SZ - 1], S0);
processTable(S0[SBOX_SK - 2], S0[SBOX_SK - 1], S1);
processTable(S1[SBOX_SK - 2], S1[SBOX_SK - 1], S2);
processTable(S2[SBOX_SK - 2], S2[SBOX_SK - 1], S3);
}
/**
* Encrypt the given input starting at the given offset and place the result
* in the provided buffer starting at the given offset. The input will be an
* exact multiple of our blocksize.
*/
private function encryptBlock(src:ByteArray, srcIndex:uint, dst:ByteArray, dstIndex:uint):void
{
var xl:uint = BytesTo32bits(src, srcIndex);
var xr:uint = BytesTo32bits(src, srcIndex + 4);
xl ^= P[0];
for (var i:uint = 1; i < ROUNDS; i += 2)
{
xr ^= F(xl) ^ P[i];
xl ^= F(xr) ^ P[i + 1];
}
xr ^= P[ROUNDS + 1];
Bits32ToBytes(xr, dst, dstIndex);
Bits32ToBytes(xl, dst, dstIndex + 4);
}
/**
* Decrypt the given input starting at the given offset and place the result
* in the provided buffer starting at the given offset. The input will be an
* exact multiple of our blocksize.
*/
private function decryptBlock(src:ByteArray, srcIndex:uint, dst:ByteArray, dstIndex:uint):void
{
var xl:uint = BytesTo32bits(src, srcIndex);
var xr:uint = BytesTo32bits(src, srcIndex + 4);
xl ^= P[ROUNDS + 1];
for (var i:uint = ROUNDS; i > 0; i -= 2)
{
xr ^= F(xl) ^ P[i];
xl ^= F(xr) ^ P[i - 1];
}
xr ^= P[0];
Bits32ToBytes(xr, dst, dstIndex);
Bits32ToBytes(xl, dst, dstIndex + 4);
}
private function BytesTo32bits(b:ByteArray, i:uint):uint
{
return ((b[i] & 0xff) << 24) | ((b[i + 1] & 0xff) << 16) | ((b[i + 2] & 0xff) << 8) | ((b[i + 3] & 0xff));
}
private function Bits32ToBytes(i:uint, b:ByteArray, offset:uint):void
{
b[offset + 3] = i;
b[offset + 2] = (i >> 8);
b[offset + 1] = (i >> 16);
b[offset] = (i >> 24);
}
public function toString():String {
return "blowfish";
}
}
}
@@ -1,55 +0,0 @@
/**
* CBCMode
*
* An ActionScript 3 implementation of the CBC confidentiality mode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
/**
* CBC confidentiality mode. why not.
*/
public class CBCMode extends IVMode implements IMode
{
public function CBCMode(key:ISymmetricKey, padding:IPad = null) {
super(key, padding);
}
public function encrypt(src:ByteArray):void {
padding.pad(src);
var vector:ByteArray = getIV4e();
for (var i:uint=0;i<src.length;i+=blockSize) {
for (var j:uint=0;j<blockSize;j++) {
src[i+j] ^= vector[j];
}
key.encrypt(src, i);
vector.position=0;
vector.writeBytes(src, i, blockSize);
}
}
public function decrypt(src:ByteArray):void {
var vector:ByteArray = getIV4d();
var tmp:ByteArray = new ByteArray;
for (var i:uint=0;i<src.length;i+=blockSize) {
tmp.position=0;
tmp.writeBytes(src, i, blockSize);
key.decrypt(src, i);
for (var j:uint=0;j<blockSize;j++) {
src[i+j] ^= vector[j];
}
vector.position=0;
vector.writeBytes(tmp, 0, blockSize);
}
padding.unpad(src);
}
public function toString():String {
return key.toString()+"-cbc";
}
}
}
@@ -1,61 +0,0 @@
/**
* CFB8Mode
*
* An ActionScript 3 implementation of the CFB-8 confidentiality mode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import com.hurlant.crypto.tests.TestCase;
import flash.utils.ByteArray;
/**
*
* Note: The constructor accepts an optional padding argument, but ignores it otherwise.
*/
public class CFB8Mode extends IVMode implements IMode
{
public function CFB8Mode(key:ISymmetricKey, padding:IPad = null) {
super(key, null);
}
public function encrypt(src:ByteArray):void {
var vector:ByteArray = getIV4e();
var tmp:ByteArray = new ByteArray;
for (var i:uint=0;i<src.length;i++) {
tmp.position = 0;
tmp.writeBytes(vector);
key.encrypt(vector);
src[i] ^= vector[0];
// rotate
for (var j:uint=0;j<blockSize-1;j++) {
vector[j] = tmp[j+1];
}
vector[blockSize-1] = src[i];
}
}
public function decrypt(src:ByteArray):void {
var vector:ByteArray = getIV4d();
var tmp:ByteArray = new ByteArray;
for (var i:uint=0;i<src.length;i++) {
var c:uint = src[i];
tmp.position = 0;
tmp.writeBytes(vector); // I <- tmp
key.encrypt(vector); // O <- vector
src[i] ^= vector[0];
// rotate
for (var j:uint=0;j<blockSize-1;j++) {
vector[j] = tmp[j+1];
}
vector[blockSize-1] = c;
}
}
public function toString():String {
return key.toString()+"-cfb8";
}
}
}
@@ -1,64 +0,0 @@
/**
* CFBMode
*
* An ActionScript 3 implementation of the CFB confidentiality mode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
/**
* This is the "full" CFB.
* CFB1 and CFB8 are hiding somewhere else.
*
* Note: The constructor accepts an optional padding argument, but ignores it otherwise.
*/
public class CFBMode extends IVMode implements IMode
{
public function CFBMode(key:ISymmetricKey, padding:IPad = null) {
super(key,null);
}
public function encrypt(src:ByteArray):void
{
var l:uint = src.length;
var vector:ByteArray = getIV4e();
for (var i:uint=0;i<src.length;i+=blockSize) {
key.encrypt(vector);
var chunk:uint = (i+blockSize<l)?blockSize:l-i;
for (var j:uint=0;j<chunk;j++) {
src[i+j] ^= vector[j];
}
vector.position=0;
vector.writeBytes(src, i, chunk);
}
}
public function decrypt(src:ByteArray):void
{
var l:uint = src.length;
var vector:ByteArray = getIV4d();
var tmp:ByteArray = new ByteArray;
for (var i:uint=0;i<src.length;i+=blockSize) {
key.encrypt(vector);
var chunk:uint = (i+blockSize<l)?blockSize:l-i;
tmp.position=0;
tmp.writeBytes(src, i, chunk);
for (var j:uint=0;j<chunk;j++) {
src[i+j] ^= vector[j];
}
vector.position=0;
vector.writeBytes(tmp);
}
}
public function toString():String {
return key.toString()+"-cfb";
}
}
}
@@ -1,58 +0,0 @@
/**
* CTRMode
*
* An ActionScript 3 implementation of the counter confidentiality mode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
public class CTRMode extends IVMode implements IMode
{
public function CTRMode(key:ISymmetricKey, padding:IPad = null) {
super(key, padding);
}
public function encrypt(src:ByteArray):void
{
padding.pad(src);
var vector:ByteArray = getIV4e();
core(src, vector);
}
public function decrypt(src:ByteArray):void
{
var vector:ByteArray = getIV4d();
core(src, vector);
padding.unpad(src);
}
private function core(src:ByteArray, iv:ByteArray):void {
var X:ByteArray = new ByteArray;
var Xenc:ByteArray = new ByteArray;
X.writeBytes(iv);
for (var i:uint=0;i<src.length;i+=blockSize) {
Xenc.position=0;
Xenc.writeBytes(X);
key.encrypt(Xenc);
for (var j:uint=0;j<blockSize;j++) {
src[i+j] ^= Xenc[j];
}
for (j=blockSize-1;j>=0;--j) {
X[j]++;
if (X[j]!=0)
break;
}
}
}
public function toString():String {
return key.toString()+"-ctr";
}
}
}
@@ -1,365 +0,0 @@
/**
* DESKey
*
* An Actionscript 3 implementation of the Data Encryption Standard (DES)
* Copyright (c) 2007 Henri Torgemane
*
* Derived from:
* The Bouncy Castle Crypto package,
* Copyright (c) 2000-2004 The Legion Of The Bouncy Castle
* (http://www.bouncycastle.org)
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
import com.hurlant.util.Hex;
import com.hurlant.util.Memory;
public class DESKey implements ISymmetricKey
{
/**
* what follows is mainly taken from "Applied Cryptography", by Bruce
* Schneier, however it also bears great resemblance to Richard
* Outerbridge's D3DES...
*/
private static const Df_Key:Array = [ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32,
0x10, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67 ];
private static const bytebit:Array = [ 128, 64, 32, 16, 8, 4, 2, 1 ];
private static const bigbyte:Array = [ 0x800000, 0x400000, 0x200000, 0x100000, 0x80000, 0x40000, 0x20000, 0x10000, 0x8000,
0x4000, 0x2000, 0x1000, 0x800, 0x400, 0x200, 0x100, 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 ];
/*
* Use the key schedule specified in the Standard (ANSI X3.92-1981).
*/
private static const pc1:Array = [ 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2,
59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12,
4, 27, 19, 11, 3 ];
private static const totrot:Array = [ 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 ];
private static const pc2:Array = [ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40,
51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 ];
private static const SP1:Array = [ 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004,
0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004,
0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004,
0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404,
0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400,
0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404,
0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004,
0x00010400, 0x00000000, 0x01010004 ];
private static const SP2:Array = [ 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020,
0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020,
0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020,
0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020,
0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020,
0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020,
0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000,
0x80100020, 0x80108020, 0x00108000 ];
private static const SP3:Array = [ 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208,
0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208,
0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208,
0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000,
0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208,
0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208,
0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208,
0x00000008, 0x08020008, 0x00020200 ];
private static const SP4:Array = [ 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001,
0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001,
0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081,
0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001,
0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081,
0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000,
0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080,
0x00800000, 0x00002000, 0x00802080 ];
private static const SP5:Array = [ 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000,
0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000,
0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000,
0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100,
0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000,
0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100,
0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000,
0x40080000, 0x02080100, 0x40000100 ];
private static const SP6:Array = [ 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010,
0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010,
0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010,
0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010,
0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000,
0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010,
0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000,
0x20000000, 0x00400010, 0x20004010 ];
private static const SP7:Array = [ 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802,
0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802,
0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000,
0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800,
0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800,
0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000,
0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002,
0x04000800, 0x00000800, 0x00200002 ];
private static const SP8:Array = [ 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040,
0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040,
0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040,
0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000,
0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040,
0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040,
0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040,
0x00040040, 0x10000000, 0x10041000 ];
protected var key:ByteArray;
protected var encKey:Array;
protected var decKey:Array;
public function DESKey(key:ByteArray) {
this.key = key;
this.encKey = generateWorkingKey(true, key, 0);
this.decKey = generateWorkingKey(false, key, 0);
}
public function getBlockSize():uint
{
return 8;
}
public function decrypt(block:ByteArray, index:uint=0):void
{
desFunc(decKey, block, index, block, index);
}
public function dispose():void
{
var i:uint=0;
for (i=0;i<encKey.length;i++) { encKey[i]=0; }
for (i=0;i<decKey.length;i++) { decKey[i]=0; }
encKey=null;
decKey=null;
for (i=0;i<key.length;i++) { key[i]=0; }
key.length = 0;
key = null;
Memory.gc();
}
public function encrypt(block:ByteArray, index:uint=0):void
{
desFunc(encKey, block, index, block, index);
}
/**
* generate an integer based working key based on our secret key and what we
* processing we are planning to do.
*
* Acknowledgements for this routine go to James Gillogly & Phil Karn.
*/
protected function generateWorkingKey(encrypting:Boolean, key:ByteArray, off:uint):Array
{
//int[] newKey = new int[32];
var newKey:Array = [];
//boolean[] pc1m = new boolean[56], pcr = new boolean[56];
var pc1m:ByteArray = new ByteArray;
var pcr:ByteArray = new ByteArray;
var l:uint;
for (var j:uint = 0; j < 56; j++)
{
l = pc1[j];
pc1m[j] = ((key[off + (l >>> 3)] & bytebit[l & 07]) != 0);
}
for (var i:uint = 0; i < 16; i++)
{
var m:uint;
var n:uint;
if (encrypting)
{
m = i << 1;
}
else
{
m = (15 - i) << 1;
}
n = m + 1;
newKey[m] = newKey[n] = 0;
for (j = 0; j < 28; j++)
{
l = j + totrot[i];
if (l < 28)
{
pcr[j] = pc1m[l];
}
else
{
pcr[j] = pc1m[l - 28];
}
}
for (j = 28; j < 56; j++)
{
l = j + totrot[i];
if (l < 56)
{
pcr[j] = pc1m[l];
}
else
{
pcr[j] = pc1m[l - 28];
}
}
for (j = 0; j < 24; j++)
{
if (pcr[pc2[j]])
{
newKey[m] |= bigbyte[j];
}
if (pcr[pc2[j + 24]])
{
newKey[n] |= bigbyte[j];
}
}
}
//
// store the processed key
//
for (i = 0; i != 32; i += 2)
{
var i1:uint;
var i2:uint;
i1 = newKey[i];
i2 = newKey[i + 1];
newKey[i] = ((i1 & 0x00fc0000) << 6) | ((i1 & 0x00000fc0) << 10) | ((i2 & 0x00fc0000) >>> 10)
| ((i2 & 0x00000fc0) >>> 6);
newKey[i + 1] = ((i1 & 0x0003f000) << 12) | ((i1 & 0x0000003f) << 16) | ((i2 & 0x0003f000) >>> 4)
| (i2 & 0x0000003f);
}
return newKey;
}
/**
* the DES engine.
*/
protected function desFunc(wKey:Array, inp:ByteArray, inOff:uint, out:ByteArray, outOff:uint):void
{
var work:uint;
var right:uint;
var left:uint;
left = (inp[inOff + 0] & 0xff) << 24;
left |= (inp[inOff + 1] & 0xff) << 16;
left |= (inp[inOff + 2] & 0xff) << 8;
left |= (inp[inOff + 3] & 0xff);
right = (inp[inOff + 4] & 0xff) << 24;
right |= (inp[inOff + 5] & 0xff) << 16;
right |= (inp[inOff + 6] & 0xff) << 8;
right |= (inp[inOff + 7] & 0xff);
work = ((left >>> 4) ^ right) & 0x0f0f0f0f;
right ^= work;
left ^= (work << 4);
work = ((left >>> 16) ^ right) & 0x0000ffff;
right ^= work;
left ^= (work << 16);
work = ((right >>> 2) ^ left) & 0x33333333;
left ^= work;
right ^= (work << 2);
work = ((right >>> 8) ^ left) & 0x00ff00ff;
left ^= work;
right ^= (work << 8);
right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff;
work = (left ^ right) & 0xaaaaaaaa;
left ^= work;
right ^= work;
left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff;
for (var round:uint = 0; round < 8; round++)
{
var fval:uint;
work = (right << 28) | (right >>> 4);
work ^= wKey[round * 4 + 0];
fval = SP7[work & 0x3f];
fval |= SP5[(work >>> 8) & 0x3f];
fval |= SP3[(work >>> 16) & 0x3f];
fval |= SP1[(work >>> 24) & 0x3f];
work = right ^ wKey[round * 4 + 1];
fval |= SP8[work & 0x3f];
fval |= SP6[(work >>> 8) & 0x3f];
fval |= SP4[(work >>> 16) & 0x3f];
fval |= SP2[(work >>> 24) & 0x3f];
left ^= fval;
work = (left << 28) | (left >>> 4);
work ^= wKey[round * 4 + 2];
fval = SP7[work & 0x3f];
fval |= SP5[(work >>> 8) & 0x3f];
fval |= SP3[(work >>> 16) & 0x3f];
fval |= SP1[(work >>> 24) & 0x3f];
work = left ^ wKey[round * 4 + 3];
fval |= SP8[work & 0x3f];
fval |= SP6[(work >>> 8) & 0x3f];
fval |= SP4[(work >>> 16) & 0x3f];
fval |= SP2[(work >>> 24) & 0x3f];
right ^= fval;
}
right = (right << 31) | (right >>> 1);
work = (left ^ right) & 0xaaaaaaaa;
left ^= work;
right ^= work;
left = (left << 31) | (left >>> 1);
work = ((left >>> 8) ^ right) & 0x00ff00ff;
right ^= work;
left ^= (work << 8);
work = ((left >>> 2) ^ right) & 0x33333333;
right ^= work;
left ^= (work << 2);
work = ((right >>> 16) ^ left) & 0x0000ffff;
left ^= work;
right ^= (work << 16);
work = ((right >>> 4) ^ left) & 0x0f0f0f0f;
left ^= work;
right ^= (work << 4);
out[outOff + 0] = ((right >>> 24) & 0xff);
out[outOff + 1] = ((right >>> 16) & 0xff);
out[outOff + 2] = ((right >>> 8) & 0xff);
out[outOff + 3] = (right & 0xff);
out[outOff + 4] = ((left >>> 24) & 0xff);
out[outOff + 5] = ((left >>> 16) & 0xff);
out[outOff + 6] = ((left >>> 8) & 0xff);
out[outOff + 7] = (left & 0xff);
}
public function toString():String {
return "des";
}
}
}
@@ -1,86 +0,0 @@
/**
* ECBMode
*
* An ActionScript 3 implementation of the ECB confidentiality mode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
import com.hurlant.util.Memory;
import com.hurlant.util.Hex;
/**
* ECB mode.
* This uses a padding and a symmetric key.
* If no padding is given, PKCS#5 is used.
*/
public class ECBMode implements IMode, ICipher
{
private var key:ISymmetricKey;
private var padding:IPad;
public function ECBMode(key:ISymmetricKey, padding:IPad = null) {
this.key = key;
if (padding == null) {
padding = new PKCS5(key.getBlockSize());
} else {
padding.setBlockSize(key.getBlockSize());
}
this.padding = padding;
}
public function getBlockSize():uint {
return key.getBlockSize();
}
public function encrypt(src:ByteArray):void {
padding.pad(src);
src.position = 0;
var blockSize:uint = key.getBlockSize();
var tmp:ByteArray = new ByteArray;
var dst:ByteArray = new ByteArray;
for (var i:uint=0;i<src.length;i+=blockSize) {
tmp.length=0;
src.readBytes(tmp, 0, blockSize);
key.encrypt(tmp);
dst.writeBytes(tmp);
}
src.length=0;
src.writeBytes(dst);
}
public function decrypt(src:ByteArray):void {
src.position = 0;
var blockSize:uint = key.getBlockSize();
// sanity check.
if (src.length%blockSize!=0) {
throw new Error("ECB mode cipher length must be a multiple of blocksize "+blockSize);
}
var tmp:ByteArray = new ByteArray;
var dst:ByteArray = new ByteArray;
for (var i:uint=0;i<src.length;i+=blockSize) {
tmp.length=0;
src.readBytes(tmp, 0, blockSize);
key.decrypt(tmp);
dst.writeBytes(tmp);
}
padding.unpad(dst);
src.length=0;
src.writeBytes(dst);
}
public function dispose():void {
key.dispose();
key = null;
padding = null;
Memory.gc();
}
public function toString():String {
return key.toString()+"-ecb";
}
}
}
@@ -1,21 +0,0 @@
/**
* ICipher
*
* A generic interface to use symmetric ciphers
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
public interface ICipher
{
function getBlockSize():uint;
function encrypt(src:ByteArray):void;
function decrypt(src:ByteArray):void;
function dispose():void;
function toString():String;
}
}
@@ -1,15 +0,0 @@
/**
* IMode
*
* An interface for confidentiality modes to implement
* This could become deprecated at some point.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
public interface IMode extends ICipher
{
}
}
@@ -1,32 +0,0 @@
/**
* IPad
*
* An interface for padding mechanisms to implement.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
/**
* Tiny interface that represents a padding mechanism.
*/
public interface IPad
{
/**
* Add padding to the array
*/
function pad(a:ByteArray):void;
/**
* Remove padding from the array.
* @throws Error if the padding is invalid.
*/
function unpad(a:ByteArray):void;
/**
* Set the blockSize to work on
*/
function setBlockSize(bs:uint):void;
}
}
@@ -1,21 +0,0 @@
/**
* IStreamCipher
*
* A "marker" interface for stream ciphers.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric {
/**
* A marker to indicate how this cipher works.
* A stream cipher:
* - does not use initialization vector
* - keeps some internal state between calls to encrypt() and decrypt()
*
*/
public interface IStreamCipher extends ICipher {
}
}
@@ -1,35 +0,0 @@
/**
* ISymmetricKey
*
* An interface for symmetric encryption keys to implement.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
public interface ISymmetricKey
{
/**
* Returns the block size used by this particular encryption algorithm
*/
function getBlockSize():uint;
/**
* Encrypt one block of data in "block", starting at "index", of length "getBlockSize()"
*/
function encrypt(block:ByteArray, index:uint=0):void;
/**
* Decrypt one block of data in "block", starting at "index", of length "getBlockSize()"
*/
function decrypt(block:ByteArray, index:uint=0):void;
/**
* Attempts to destroy sensitive information from memory, such as encryption keys.
* Note: This is not guaranteed to work given the Flash sandbox model.
*/
function dispose():void;
function toString():String;
}
}
@@ -1,110 +0,0 @@
/**
* IVMode
*
* An abstract class for confidentialy modes that rely on an initialization vector.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import com.hurlant.crypto.prng.Random;
import com.hurlant.crypto.tests.TestCase;
import com.hurlant.util.Memory;
import flash.utils.ByteArray;
/**
* An "abtract" class to avoid redundant code in subclasses
*/
public class IVMode
{
protected var key:ISymmetricKey;
protected var padding:IPad;
// random generator used to generate IVs
protected var prng:Random;
// optional static IV. used for testing only.
protected var iv:ByteArray;
// generated IV is stored here.
protected var lastIV:ByteArray;
protected var blockSize:uint;
public function IVMode(key:ISymmetricKey, padding:IPad = null) {
this.key = key;
blockSize = key.getBlockSize();
if (padding == null) {
padding = new PKCS5(blockSize);
} else {
padding.setBlockSize(blockSize);
}
this.padding = padding;
prng = new Random;
iv = null;
lastIV = new ByteArray;
}
public function getBlockSize():uint {
return key.getBlockSize();
}
public function dispose():void {
var i:uint;
if (iv != null) {
for (i=0;i<iv.length;i++) {
iv[i] = prng.nextByte();
}
iv.length=0;
iv = null;
}
if (lastIV != null) {
for (i=0;i<iv.length;i++) {
lastIV[i] = prng.nextByte();
}
lastIV.length=0;
lastIV=null;
}
key.dispose();
key = null;
padding = null;
prng.dispose();
prng = null;
Memory.gc();
}
/**
* Optional function to force the IV value.
* Normally, an IV gets generated randomly at every encrypt() call.
* Also, use this to set the IV before calling decrypt()
* (if not set before decrypt(), the IV is read from the beginning of the stream.)
*/
public function set IV(value:ByteArray):void {
iv = value;
lastIV.length=0;
lastIV.writeBytes(iv);
}
public function get IV():ByteArray {
return lastIV;
}
protected function getIV4e():ByteArray {
var vec:ByteArray = new ByteArray;
if (iv) {
vec.writeBytes(iv);
} else {
prng.nextBytes(vec, blockSize);
}
lastIV.length=0;
lastIV.writeBytes(vec);
return vec;
}
protected function getIV4d():ByteArray {
var vec:ByteArray = new ByteArray;
if (iv) {
vec.writeBytes(iv);
} else {
throw new Error("an IV must be set before calling decrypt()");
}
return vec;
}
}
}
@@ -1,34 +0,0 @@
/**
* NullPad
*
* A padding class that doesn't pad.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
/**
* A pad that does nothing.
* Useful when you don't want padding in your Mode.
*/
public class NullPad implements IPad
{
public function unpad(a:ByteArray):void
{
return;
}
public function pad(a:ByteArray):void
{
return;
}
public function setBlockSize(bs:uint):void {
return;
}
}
}
@@ -1,52 +0,0 @@
/**
* OFBMode
*
* An ActionScript 3 implementation of the OFB confidentiality mode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
public class OFBMode extends IVMode implements IMode
{
public function OFBMode(key:ISymmetricKey, padding:IPad=null)
{
super(key, null);
}
public function encrypt(src:ByteArray):void
{
var vector:ByteArray = getIV4e();
core(src, vector);
}
public function decrypt(src:ByteArray):void
{
var vector:ByteArray = getIV4d();
core(src, vector);
}
private function core(src:ByteArray, iv:ByteArray):void {
var l:uint = src.length;
var tmp:ByteArray = new ByteArray;
for (var i:uint=0;i<src.length;i+=blockSize) {
key.encrypt(iv);
tmp.position=0;
tmp.writeBytes(iv);
var chunk:uint = (i+blockSize<l)?blockSize:l-i;
for (var j:uint=0;j<chunk;j++) {
src[i+j] ^= iv[j];
}
iv.position=0;
iv.writeBytes(tmp);
}
}
public function toString():String {
return key.toString()+"-ofb";
}
}
}
@@ -1,44 +0,0 @@
/**
* PKCS5
*
* A padding implementation of PKCS5.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
public class PKCS5 implements IPad
{
private var blockSize:uint;
public function PKCS5(blockSize:uint=0) {
this.blockSize = blockSize;
}
public function pad(a:ByteArray):void {
var c:uint = blockSize-a.length%blockSize;
for (var i:uint=0;i<c;i++){
a[a.length] = c;
}
}
public function unpad(a:ByteArray):void {
var c:uint = a.length%blockSize;
if (c!=0) throw new Error("PKCS#5::unpad: ByteArray.length isn't a multiple of the blockSize");
c = a[a.length-1];
for (var i:uint=c;i>0;i--) {
var v:uint = a[a.length-1];
a.length--;
if (c!=v) throw new Error("PKCS#5:unpad: Invalid padding value. expected ["+c+"], found ["+v+"]");
}
// that is all.
}
public function setBlockSize(bs:uint):void {
blockSize = bs;
}
}
}
@@ -1,44 +0,0 @@
/**
* TLSPad
*
* A padding implementation used by TLS
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric {
import flash.utils.ByteArray;
import com.hurlant.util.Hex;
import com.hurlant.crypto.tls.TLSError;
public class SSLPad implements IPad {
private var blockSize:uint;
public function SSLPad(blockSize:uint=0) {
this.blockSize = blockSize;
}
public function pad(a:ByteArray):void {
var c:uint = blockSize - (a.length+1)%blockSize;
for (var i:uint=0;i<=c;i++) {
a[a.length] = c;
}
}
public function unpad(a:ByteArray):void {
var c:uint = a.length%blockSize;
if (c!=0) throw new TLSError("SSLPad::unpad: ByteArray.length isn't a multiple of the blockSize", TLSError.bad_record_mac);
c = a[a.length-1];
for (var i:uint=c;i>0;i--) {
var v:uint = a[a.length-1];
a.length--;
// But LOOK! SSL 3.0 doesn't care about this, bytes are arbitrary!
// if (c!=v) throw new TLSError("SSLPad:unpad: Invalid padding value. expected ["+c+"], found ["+v+"]", TLSError.bad_record_mac);
}
a.length--;
}
public function setBlockSize(bs:uint):void {
blockSize = bs;
}
}
}
@@ -1,60 +0,0 @@
/**
* SimpleIVMode
*
* A convenience class that automatically places the IV
* at the beginning of the encrypted stream, so it doesn't have to
* be handled explicitely.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
import com.hurlant.util.Memory;
public class SimpleIVMode implements IMode, ICipher
{
protected var mode:IVMode;
protected var cipher:ICipher;
public function SimpleIVMode(mode:IVMode) {
this.mode = mode;
cipher = mode as ICipher;
}
public function getBlockSize():uint {
return mode.getBlockSize();
}
public function dispose():void {
mode.dispose();
mode = null;
cipher = null;
Memory.gc();
}
public function encrypt(src:ByteArray):void {
cipher.encrypt(src);
var tmp:ByteArray = new ByteArray;
tmp.writeBytes(mode.IV);
tmp.writeBytes(src);
src.position=0;
src.writeBytes(tmp);
}
public function decrypt(src:ByteArray):void {
var tmp:ByteArray = new ByteArray;
tmp.writeBytes(src, 0, getBlockSize());
mode.IV = tmp;
tmp = new ByteArray;
tmp.writeBytes(src, getBlockSize());
cipher.decrypt(tmp);
src.length=0;
src.writeBytes(tmp);
}
public function toString():String {
return "simple-"+cipher.toString();
}
}
}
@@ -1,42 +0,0 @@
/**
* TLSPad
*
* A padding implementation used by TLS
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric {
import flash.utils.ByteArray;
import com.hurlant.util.Hex;
import com.hurlant.crypto.tls.TLSError;
public class TLSPad implements IPad {
private var blockSize:uint;
public function TLSPad(blockSize:uint=0) {
this.blockSize = blockSize;
}
public function pad(a:ByteArray):void {
var c:uint = blockSize - (a.length+1)%blockSize;
for (var i:uint=0;i<=c;i++) {
a[a.length] = c;
}
}
public function unpad(a:ByteArray):void {
var c:uint = a.length%blockSize;
if (c!=0) throw new TLSError("TLSPad::unpad: ByteArray.length isn't a multiple of the blockSize", TLSError.bad_record_mac);
c = a[a.length-1];
for (var i:uint=c;i>0;i--) {
var v:uint = a[a.length-1];
a.length--;
if (c!=v) throw new TLSError("TLSPad:unpad: Invalid padding value. expected ["+c+"], found ["+v+"]", TLSError.bad_record_mac);
}
a.length--;
// mostly ripped off from PKCS5.as, but with subtle differences
}
public function setBlockSize(bs:uint):void {
blockSize = bs;
}
}
}
@@ -1,88 +0,0 @@
/**
* TripleDESKey
*
* An Actionscript 3 implementation of Triple DES
* Copyright (c) 2007 Henri Torgemane
*
* Derived from:
* The Bouncy Castle Crypto package,
* Copyright (c) 2000-2004 The Legion Of The Bouncy Castle
* (http://www.bouncycastle.org)
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
import com.hurlant.util.Memory;
import com.hurlant.util.Hex;
public class TripleDESKey extends DESKey
{
protected var encKey2:Array;
protected var encKey3:Array;
protected var decKey2:Array;
protected var decKey3:Array;
/**
* This supports 2TDES and 3TDES.
* If the key passed is 128 bits, 2TDES is used.
* If the key has 192 bits, 3TDES is used.
* Other key lengths give "undefined" results.
*/
public function TripleDESKey(key:ByteArray)
{
super(key);
encKey2 = generateWorkingKey(false, key, 8);
decKey2 = generateWorkingKey(true, key, 8);
if (key.length>16) {
encKey3 = generateWorkingKey(true, key, 16);
decKey3 = generateWorkingKey(false, key, 16);
} else {
encKey3 = encKey;
decKey3 = decKey;
}
}
public override function dispose():void
{
super.dispose();
var i:uint = 0;
if (encKey2!=null) {
for (i=0;i<encKey2.length;i++) { encKey2[i]=0; }
encKey2=null;
}
if (encKey3!=null) {
for (i=0;i<encKey3.length;i++) { encKey3[i]=0; }
encKey3=null;
}
if (decKey2!=null) {
for (i=0;i<decKey2.length;i++) { decKey2[i]=0; }
decKey2=null
}
if (decKey3!=null) {
for (i=0;i<decKey3.length;i++) { decKey3[i]=0; }
decKey3=null;
}
Memory.gc();
}
public override function encrypt(block:ByteArray, index:uint=0):void
{
desFunc(encKey, block,index, block,index);
desFunc(encKey2, block,index, block,index);
desFunc(encKey3, block,index, block,index);
}
public override function decrypt(block:ByteArray, index:uint=0):void
{
desFunc(decKey3, block, index, block, index);
desFunc(decKey2, block, index, block, index);
desFunc(decKey, block, index, block, index);
}
public override function toString():String {
return "3des";
}
}
}
@@ -1,94 +0,0 @@
/**
* XTeaKey
*
* An ActionScript 3 implementation of the XTea algorithm
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import com.hurlant.crypto.prng.Random;
import com.hurlant.util.Memory;
import flash.utils.ByteArray;
public class XTeaKey implements ISymmetricKey
{
public const NUM_ROUNDS:uint = 64;
private var k:Array;
public function XTeaKey(a:ByteArray) {
a.position=0;
k = [a.readUnsignedInt(),a.readUnsignedInt(),a.readUnsignedInt(),a.readUnsignedInt()];
}
/**
* K is an hex string with 32 digits.
*/
public static function parseKey(K:String):XTeaKey {
var a:ByteArray = new ByteArray;
a.writeUnsignedInt(parseInt(K.substr(0,8),16));
a.writeUnsignedInt(parseInt(K.substr(8,8),16));
a.writeUnsignedInt(parseInt(K.substr(16,8),16));
a.writeUnsignedInt(parseInt(K.substr(24,8),16));
a.position = 0;
return new XTeaKey(a);
}
public function getBlockSize():uint {
return 8;
}
public function encrypt(block:ByteArray, index:uint=0):void {
block.position = index;
var v0:uint = block.readUnsignedInt();
var v1:uint = block.readUnsignedInt();
var i:uint;
var sum:uint =0;
var delta:uint = 0x9E3779B9;
for (i=0; i<NUM_ROUNDS; i++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
}
block.position-=8;
block.writeUnsignedInt(v0);
block.writeUnsignedInt(v1);
}
public function decrypt(block:ByteArray, index:uint=0):void {
block.position = index;
var v0:uint = block.readUnsignedInt();
var v1:uint = block.readUnsignedInt();
var i:uint;
var delta:uint = 0x9E3779B9;
var sum:uint = delta*NUM_ROUNDS;
for (i=0; i<NUM_ROUNDS; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
}
block.position-=8;
block.writeUnsignedInt(v0);
block.writeUnsignedInt(v1);
}
public function dispose():void {
//private var k:Array;
var r:Random = new Random;
for (var i:uint=0;i<k.length;i++) {
k[i] = r.nextByte();
delete k[i];
}
k = null;
Memory.gc();
}
public function toString():String {
return "xtea";
}
}
}
@@ -1,29 +0,0 @@
#!/usr/bin/perl
use strict;
use warnings;
sub say {
my $w = shift;
print $w;
print "\n";
}
sub dump {
my $i = shift;
&say(sprintf("Sbox[%d] = _Sbox[%d]", $i, $i));
&say(sprintf("InvSbox[%d] = _InvSbox[%d]", $i, $i));
&say(sprintf("Xtime2Sbox[%d] = _Xtime2Sbox[%d]", $i, $i));
&say(sprintf("Xtime3Sbox[%d] = _Xtime3Sbox[%d]", $i, $i));
&say(sprintf("Xtime2[%d] = _Xtime2[%d]", $i, $i));
&say(sprintf("Xtime9[%d] = _Xtime9[%d]", $i, $i));
&say(sprintf("XtimeB[%d] = _XtimeB[%d]", $i, $i));
&say(sprintf("XtimeD[%d] = _XtimeD[%d]", $i, $i));
&say(sprintf("XtimeE[%d] = _XtimeE[%d]", $i, $i));
}
for (my $i=0;$i<256;$i++) {
&dump($i);
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,58 +0,0 @@
/**
* ARC4Test
*
* A test class for ARC4
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import com.hurlant.util.Hex;
import flash.utils.ByteArray;
import com.hurlant.crypto.prng.ARC4;
public class ARC4Test extends TestCase
{
public function ARC4Test(h:ITestHarness)
{
super(h, "ARC4 Test");
runTest(testLameVectors,"ARC4 Test Vectors");
h.endTestCase();
}
/**
* Sad test vectors pilfered from
* http://en.wikipedia.org/wiki/RC4
*/
public function testLameVectors():void {
var keys:Array = [
Hex.fromString("Key"),
Hex.fromString("Wiki"),
Hex.fromString("Secret")];
var pts:Array = [
Hex.fromString("Plaintext"),
Hex.fromString("pedia"),
Hex.fromString("Attack at dawn")];
var cts:Array = [
"BBF316E8D940AF0AD3",
"1021BF0420",
"45A01F645FC35B383552544B9BF5"];
for (var i:uint=0;i<keys.length;i++) {
var key:ByteArray = Hex.toArray(keys[i]);
var pt:ByteArray = Hex.toArray(pts[i]);
var rc4:ARC4 = new ARC4(key);
rc4.encrypt(pt);
var out:String = Hex.fromArray(pt).toUpperCase();
assert("comparing "+cts[i]+" to "+out, cts[i]==out);
// now go back to plaintext
rc4.init(key);
rc4.decrypt(pt);
out = Hex.fromArray(pt);
assert("comparing "+pts[i]+" to "+out, pts[i]==out);
}
}
}
}
@@ -1,39 +0,0 @@
/**
* BigIntegerTest
*
* A test class for BigInteger
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import com.hurlant.math.BigInteger;
import com.hurlant.util.Hex;
public class BigIntegerTest extends TestCase
{
public function BigIntegerTest(h:ITestHarness)
{
super(h, "BigInteger Tests");
runTest(testAdd, "BigInteger Addition");
h.endTestCase();
}
public function testAdd():void {
var n1:BigInteger = BigInteger.nbv(25);
var n2:BigInteger = BigInteger.nbv(1002);
var n3:BigInteger = n1.add(n2);
var v:int = n3.valueOf();
assert("25+1002 = "+v, 25+1002==v);
var p:BigInteger = new BigInteger(Hex.toArray("e564d8b801a61f47"));
var xp:BigInteger = new BigInteger(Hex.toArray("99246db2a3507fa"));
xp = xp.add(p);
assert("xp==eef71f932bdb2741", xp.toString(16)=="eef71f932bdb2741");
}
}
}
@@ -1,148 +0,0 @@
/**
* BlowFishKeyTest
*
* A test class for BlowFishKey
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import com.hurlant.crypto.symmetric.BlowFishKey;
import com.hurlant.util.Hex;
import flash.utils.ByteArray;
public class BlowFishKeyTest extends TestCase
{
public function BlowFishKeyTest(h:ITestHarness)
{
super(h, "BlowFishKey Test");
runTest(testECB,"BlowFish ECB Test Vectors");
h.endTestCase();
}
/**
* Test vectors from http://www.schneier.com/code/vectors.txt
*/
public function testECB():void {
var keys:Array = [
"0000000000000000",
"FFFFFFFFFFFFFFFF",
"3000000000000000",
"1111111111111111",
"0123456789ABCDEF",
"1111111111111111",
"0000000000000000",
"FEDCBA9876543210",
"7CA110454A1A6E57",
"0131D9619DC1376E",
"07A1133E4A0B2686",
"3849674C2602319E",
"04B915BA43FEB5B6",
"0113B970FD34F2CE",
"0170F175468FB5E6",
"43297FAD38E373FE",
"07A7137045DA2A16",
"04689104C2FD3B2F",
"37D06BB516CB7546",
"1F08260D1AC2465E",
"584023641ABA6176",
"025816164629B007",
"49793EBC79B3258F",
"4FB05E1515AB73A7",
"49E95D6D4CA229BF",
"018310DC409B26D6",
"1C587F1C13924FEF",
"0101010101010101",
"1F1F1F1F0E0E0E0E",
"E0FEE0FEF1FEF1FE",
"0000000000000000",
"FFFFFFFFFFFFFFFF",
"0123456789ABCDEF",
"FEDCBA9876543210" ];
var pts:Array = [
"0000000000000000",
"FFFFFFFFFFFFFFFF",
"1000000000000001",
"1111111111111111",
"1111111111111111",
"0123456789ABCDEF",
"0000000000000000",
"0123456789ABCDEF",
"01A1D6D039776742",
"5CD54CA83DEF57DA",
"0248D43806F67172",
"51454B582DDF440A",
"42FD443059577FA2",
"059B5E0851CF143A",
"0756D8E0774761D2",
"762514B829BF486A",
"3BDD119049372802",
"26955F6835AF609A",
"164D5E404F275232",
"6B056E18759F5CCA",
"004BD6EF09176062",
"480D39006EE762F2",
"437540C8698F3CFA",
"072D43A077075292",
"02FE55778117F12A",
"1D9D5C5018F728C2",
"305532286D6F295A",
"0123456789ABCDEF",
"0123456789ABCDEF",
"0123456789ABCDEF",
"FFFFFFFFFFFFFFFF",
"0000000000000000",
"0000000000000000",
"FFFFFFFFFFFFFFFF" ];
var cts:Array = [
"4EF997456198DD78",
"51866FD5B85ECB8A",
"7D856F9A613063F2",
"2466DD878B963C9D",
"61F9C3802281B096",
"7D0CC630AFDA1EC7",
"4EF997456198DD78",
"0ACEAB0FC6A0A28D",
"59C68245EB05282B",
"B1B8CC0B250F09A0",
"1730E5778BEA1DA4",
"A25E7856CF2651EB",
"353882B109CE8F1A",
"48F4D0884C379918",
"432193B78951FC98",
"13F04154D69D1AE5",
"2EEDDA93FFD39C79",
"D887E0393C2DA6E3",
"5F99D04F5B163969",
"4A057A3B24D3977B",
"452031C1E4FADA8E",
"7555AE39F59B87BD",
"53C55F9CB49FC019",
"7A8E7BFA937E89A3",
"CF9C5D7A4986ADB5",
"D1ABB290658BC778",
"55CB3774D13EF201",
"FA34EC4847B268B2",
"A790795108EA3CAE",
"C39E072D9FAC631D",
"014933E0CDAFF6E4",
"F21E9A77B71C49BC",
"245946885754369A",
"6B5C5A9C5D9E0A5A" ];
for (var i:uint=0;i<keys.length;i++) {
var key:ByteArray = Hex.toArray(keys[i]);
var pt:ByteArray = Hex.toArray(pts[i]);
var bf:BlowFishKey = new BlowFishKey(key);
bf.encrypt(pt);
var out:String = Hex.fromArray(pt).toUpperCase();
assert("comparing "+cts[i]+" to "+out, cts[i]==out);
// now go back to plaintext
bf.decrypt(pt);
out = Hex.fromArray(pt).toUpperCase();
assert("comparing "+pts[i]+" to "+out, pts[i]==out);
}
}
}
}
@@ -1,160 +0,0 @@
/**
* CBCModeTest
*
* A test class for CBCMode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import com.hurlant.crypto.symmetric.AESKey;
import com.hurlant.crypto.symmetric.CBCMode;
import com.hurlant.crypto.symmetric.NullPad;
import com.hurlant.crypto.symmetric.XTeaKey;
import com.hurlant.util.Hex;
import flash.utils.ByteArray;
public class CBCModeTest extends TestCase
{
public function CBCModeTest(h:ITestHarness) {
super(h, "CBCMode Test");
runTest(testAES,"CBC AES Test Vectors");
runTest(testXTea,"CBC XTea Test Vectors");
//
runTest(testCBC_AES128, "CBC AES-128 Test Vectors");
runTest(testCBC_AES192, "CBC AES-192 Test Vectors");
runTest(testCBC_AES256, "CBC AES-256 Test Vectors");
h.endTestCase();
}
/**
* Hawt NIST Vectors: http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
* Section F.2.1 and below.
*/
public function testCBC_AES128():void {
var key:ByteArray = Hex.toArray("2b7e151628aed2a6abf7158809cf4f3c");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"7649abac8119b246cee98e9b12e9197d" +
"5086cb9b507219ee95db113a917678b2" +
"73bed6b8e3c1743b7116e69e22229516" +
"3ff1caa1681fac09120eca307586e1a7");
var cbc:CBCMode = new CBCMode(new AESKey(key), new NullPad);
cbc.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
cbc.encrypt(src);
assert("CBC_AES128 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
cbc.decrypt(src);
assert("CBC_AES128 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
public function testCBC_AES192():void {
var key:ByteArray = Hex.toArray("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"4f021db243bc633d7178183a9fa071e8" +
"b4d9ada9ad7dedf4e5e738763f69145a" +
"571b242012fb7ae07fa9baac3df102e0" +
"08b0e27988598881d920a9e64f5615cd");
var cbc:CBCMode = new CBCMode(new AESKey(key), new NullPad);
cbc.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
cbc.encrypt(src);
assert("CBC_AES192 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
cbc.decrypt(src);
assert("CBC_AES192 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
public function testCBC_AES256():void {
var key:ByteArray = Hex.toArray(
"603deb1015ca71be2b73aef0857d7781" +
"1f352c073b6108d72d9810a30914dff4");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"f58c4c04d6e5f1ba779eabfb5f7bfbd6" +
"9cfc4e967edb808d679f777bc6702c7d" +
"39f23369a9d9bacfa530e26304231461" +
"b2eb05e2c39be9fcda6c19078c6a9d1b");
var cbc:CBCMode = new CBCMode(new AESKey(key), new NullPad);
cbc.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
cbc.encrypt(src);
assert("CBC_AES256 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
cbc.decrypt(src);
assert("CBC_AES256 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
/**
* For now the main goal is to show we can decrypt what we encrypt in this mode.
* Eventually, this should get correlated with some well known vectors.
*/
public function testAES():void {
var keys:Array = [
"00010203050607080A0B0C0D0F101112",
"14151617191A1B1C1E1F202123242526"];
var cts:Array = [
"D8F532538289EF7D06B506A4FD5BE9C94894C5508A8D8E29AB600DB0261F0555A8FA287B89E65C0973F1F8283E70C72863FE1C8F1F782084CE05626E961A67B3",
"59AB30F4D4EE6E4FF9907EF65B1FB68C96890CE217689B1BE0C93ED51CF21BB5A0101A8C30714EC4F52DBC9C6F4126067D363F67ABE58463005E679B68F0B496"];
var pts:Array = [
"506812A45F08C889B97F5980038B8359506812A45F08C889B97F5980038B8359506812A45F08C889B97F5980038B8359",
"5C6D71CA30DE8B8B00549984D2EC7D4B5C6D71CA30DE8B8B00549984D2EC7D4B5C6D71CA30DE8B8B00549984D2EC7D4B"];
for (var i:uint=0;i<keys.length;i++) {
var key:ByteArray = Hex.toArray(keys[i]);
var pt:ByteArray = Hex.toArray(pts[i]);
var aes:AESKey = new AESKey(key);
var cbc:CBCMode = new CBCMode(aes);
cbc.IV = Hex.toArray("00000000000000000000000000000000");
cbc.encrypt(pt);
var str:String = Hex.fromArray(pt).toUpperCase();
assert("comparing "+cts[i]+" to "+str, cts[i]==str);
// back to pt
cbc.decrypt(pt);
str = Hex.fromArray(pt).toUpperCase();
assert("comparing "+pts[i]+" to "+str, pts[i]==str);
}
}
public function testXTea():void {
var keys:Array=[
"00000000000000000000000000000000",
"2b02056806144976775d0e266c287843"];
var cts:Array = [
"2dc7e8d3695b0538d8f1640d46dca717790af2ab545e11f3b08e798eb3f17b1744299d4d20b534aa",
"790958213819878370eb8251ffdac371081c5a457fc42502c63910306fea150be8674c3b8e675516"];
var pts:Array=[
"0000000000000000000000000000000000000000000000000000000000000000",
"74657374206d652e74657374206d652e74657374206d652e74657374206d652e"];
for (var i:uint=0;i<keys.length;i++) {
var key:ByteArray = Hex.toArray(keys[i]);
var pt:ByteArray = Hex.toArray(pts[i]);
var tea:XTeaKey = new XTeaKey(key);
var cbc:CBCMode = new CBCMode(tea);
cbc.IV = Hex.toArray("0000000000000000");
cbc.encrypt(pt);
var str:String = Hex.fromArray(pt);
assert("comparing "+cts[i]+" to "+str, cts[i]==str);
// now go back to plaintext.
cbc.decrypt(pt);
str = Hex.fromArray(pt);
assert("comparing "+pts[i]+" to "+str, pts[i]==str);
}
}
}
}
@@ -1,71 +0,0 @@
/**
* CFB8ModeTest
*
* A test class for CFB8Mode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import flash.utils.ByteArray;
import com.hurlant.util.Hex;
import com.hurlant.crypto.symmetric.CFB8Mode;
import com.hurlant.crypto.symmetric.AESKey;
import com.hurlant.crypto.symmetric.NullPad;
public class CFB8ModeTest extends TestCase
{
public function CFB8ModeTest(h:ITestHarness) {
super(h,"CBF8Mode Test");
runTest(testCFB8_AES128, "CFB-8 AES-128 Test Vectors");
runTest(testCFB8_AES192, "CFB-8 AES-192 Test Vectors");
runTest(testCFB8_AES256, "CFB-8 AES-192 Test Vectors");
h.endTestCase();
}
/**
* http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
*/
public function testCFB8_AES128():void {
var key:ByteArray = Hex.toArray("2b7e151628aed2a6abf7158809cf4f3c");
var pt:ByteArray = Hex.toArray("6bc1bee22e409f96e93d7e117393172aae2d");
var ct:ByteArray = Hex.toArray("3b79424c9c0dd436bace9e0ed4586a4f32b9");
var cfb8:CFB8Mode = new CFB8Mode(new AESKey(key), new NullPad);
cfb8.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
cfb8.encrypt(src);
assert("CFB8_AES128 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
cfb8.decrypt(src);
assert("CFB8_AES128 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
public function testCFB8_AES192():void {
var key:ByteArray = Hex.toArray("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b");
var pt:ByteArray = Hex.toArray("6bc1bee22e409f96e93d7e117393172aae2d");
var ct:ByteArray = Hex.toArray("cda2521ef0a905ca44cd057cbf0d47a0678a");
var cfb8:CFB8Mode = new CFB8Mode(new AESKey(key), new NullPad);
cfb8.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
cfb8.encrypt(src);
assert("CFB8_AES128 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
cfb8.decrypt(src);
assert("CFB8_AES128 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
public function testCFB8_AES256():void {
var key:ByteArray = Hex.toArray("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4");
var pt:ByteArray = Hex.toArray("6bc1bee22e409f96e93d7e117393172aae2d");
var ct:ByteArray = Hex.toArray("dc1f1a8520a64db55fcc8ac554844e889700");
var cfb8:CFB8Mode = new CFB8Mode(new AESKey(key), new NullPad);
cfb8.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
cfb8.encrypt(src);
assert("CFB8_AES128 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
cfb8.decrypt(src);
assert("CFB8_AES128 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
}
}
@@ -1,98 +0,0 @@
/**
* CFBModeTest
*
* A test class for CFBMode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import com.hurlant.crypto.symmetric.AESKey;
import com.hurlant.crypto.symmetric.CFBMode;
import com.hurlant.crypto.symmetric.NullPad;
import com.hurlant.util.Hex;
import flash.utils.ByteArray;
public class CFBModeTest extends TestCase
{
public function CFBModeTest(h:ITestHarness)
{
super(h, "CFBMode Test");
runTest(testCFB_AES128, "CFB AES-128 Test Vectors");
runTest(testCFB_AES192, "CFB AES-192 Test Vectors");
runTest(testCFB_AES256, "CFB AES-256 Test Vectors");
h.endTestCase();
}
/**
* http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
*/
public function testCFB_AES128():void {
var key:ByteArray = Hex.toArray("2b7e151628aed2a6abf7158809cf4f3c");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"3b3fd92eb72dad20333449f8e83cfb4a" +
"c8a64537a0b3a93fcde3cdad9f1ce58b" +
"26751f67a3cbb140b1808cf187a4f4df" +
"c04b05357c5d1c0eeac4c66f9ff7f2e6");
var cfb:CFBMode = new CFBMode(new AESKey(key), new NullPad);
cfb.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
cfb.encrypt(src);
assert("CFB_AES128 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
cfb.decrypt(src);
assert("CFB_AES128 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
public function testCFB_AES192():void {
var key:ByteArray = Hex.toArray("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"cdc80d6fddf18cab34c25909c99a4174" +
"67ce7f7f81173621961a2b70171d3d7a" +
"2e1e8a1dd59b88b1c8e60fed1efac4c9" +
"c05f9f9ca9834fa042ae8fba584b09ff");
var cfb:CFBMode = new CFBMode(new AESKey(key), new NullPad);
cfb.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
cfb.encrypt(src);
assert("CFB_AES192 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
cfb.decrypt(src);
assert("CFB_AES192 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
public function testCFB_AES256():void {
var key:ByteArray = Hex.toArray(
"603deb1015ca71be2b73aef0857d7781" +
"1f352c073b6108d72d9810a30914dff4");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"dc7e84bfda79164b7ecd8486985d3860" +
"39ffed143b28b1c832113c6331e5407b" +
"df10132415e54b92a13ed0a8267ae2f9" +
"75a385741ab9cef82031623d55b1e471");
var cfb:CFBMode = new CFBMode(new AESKey(key), new NullPad);
cfb.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
cfb.encrypt(src);
assert("CFB_AES256 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
cfb.decrypt(src);
assert("CFB_AES256 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
}
}
@@ -1,109 +0,0 @@
/**
* CTRModeTest
*
* A test class for CTRMode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import flash.utils.ByteArray;
import com.hurlant.util.Hex;
import com.hurlant.crypto.symmetric.CTRMode;
import com.hurlant.crypto.symmetric.AESKey;
import com.hurlant.crypto.symmetric.NullPad;
public class CTRModeTest extends TestCase
{
public function CTRModeTest(h:ITestHarness)
{
super(h, "CTRMode Test");
runTest(testCTR_AES128, "CTR AES-128 Test Vectors");
runTest(testCTR_AES192, "CTR AES-192 Test Vectors");
runTest(testCTR_AES256, "CTR AES-256 Test Vectors");
h.endTestCase();
}
/**
* Vectors from http://csrc.nist.gov/CryptoToolkit/modes/800-38_Series_Publications/SP800-38A.pdf
* Section F.5.1 and below.
*/
public function testCTR_AES128():void {
var key:ByteArray = Hex.toArray("2b7e151628aed2a6abf7158809cf4f3c");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"874d6191b620e3261bef6864990db6ce" +
"9806f66b7970fdff8617187bb9fffdff" +
"5ae4df3edbd5d35e5b4f09020db03eab" +
"1e031dda2fbe03d1792170a0f3009cee");
var ctr:CTRMode = new CTRMode(new AESKey(key), new NullPad);
ctr.IV = Hex.toArray("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
ctr.encrypt(src);
var hsrc:String = Hex.fromArray(src);
var hct:String = Hex.fromArray(ct);
assert("CTR_AES128 test 1: "+hsrc+" != "+hct, hsrc==hct);
ctr.decrypt(src);
hsrc = Hex.fromArray(src);
var hpt:String = Hex.fromArray(pt);
assert("CTR_AES128 test 2: "+hsrc+" != "+hpt, hsrc==hpt);
}
public function testCTR_AES192():void {
var key:ByteArray = Hex.toArray("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"1abc932417521ca24f2b0459fe7e6e0b" +
"090339ec0aa6faefd5ccc2c6f4ce8e94" +
"1e36b26bd1ebc670d1bd1d665620abf7" +
"4f78a7f6d29809585a97daec58c6b050");
var ctr:CTRMode = new CTRMode(new AESKey(key), new NullPad);
ctr.IV = Hex.toArray("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
ctr.encrypt(src);
var hsrc:String = Hex.fromArray(src);
var hct:String = Hex.fromArray(ct);
assert("CTR_AES192 test 1: "+hsrc+" != "+hct, hsrc==hct);
ctr.decrypt(src);
hsrc = Hex.fromArray(src);
var hpt:String = Hex.fromArray(pt);
assert("CTR_AES192 test 2: "+hsrc+" != "+hpt, hsrc==hpt);
}
public function testCTR_AES256():void {
var key:ByteArray = Hex.toArray("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"601ec313775789a5b7a7f504bbf3d228" +
"f443e3ca4d62b59aca84e990cacaf5c5" +
"2b0930daa23de94ce87017ba2d84988d" +
"dfc9c58db67aada613c2dd08457941a6");
var ctr:CTRMode = new CTRMode(new AESKey(key), new NullPad);
ctr.IV = Hex.toArray("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
ctr.encrypt(src);
var hsrc:String = Hex.fromArray(src);
var hct:String = Hex.fromArray(ct);
assert("CTR_AES256 test 1: "+hsrc+" != "+hct, hsrc==hct);
ctr.decrypt(src);
hsrc = Hex.fromArray(src);
var hpt:String = Hex.fromArray(pt);
assert("CTR_AES256 test 2: "+hsrc+" != "+hpt, hsrc==hpt);
}
}
}

Some files were not shown because too many files have changed in this diff Show More