Compare commits
18 Commits
master
...
primalmoti
| Author | SHA1 | Date |
|---|---|---|
|
|
11f3271a52 | |
|
|
8ded53c1de | |
|
|
434699bf23 | |
|
|
5e5d81dd86 | |
|
|
f8f5c923dd | |
|
|
93c860e8e5 | |
|
|
78223532ce | |
|
|
9fc59562a1 | |
|
|
045c117dbb | |
|
|
eb7b25ae17 | |
|
|
edd9a72c0e | |
|
|
9046dbf244 | |
|
|
5c7418cf36 | |
|
|
61bddad2ea | |
|
|
30a532d38c | |
|
|
212733afbf | |
|
|
33ebb52b56 | |
|
|
ed5573e806 |
|
|
@ -1,19 +0,0 @@
|
|||
name: Lint
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Update pip and setuptools
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install setuptools
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install flake8
|
||||
- name: Lint with flake8
|
||||
run: |
|
||||
flake8
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
name: Test
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: python:${{ matrix.python-version }}
|
||||
strategy:
|
||||
matrix:
|
||||
python-version:
|
||||
- 3.6
|
||||
- 3.7
|
||||
- 3.8
|
||||
- 3.9
|
||||
- "3.10"
|
||||
- 3.11
|
||||
- 3.12
|
||||
- 3.13
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Update pip and setuptools
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install setuptools
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install -e .
|
||||
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 -m nose2 --verbosity=3
|
||||
|
|
@ -1,12 +1,4 @@
|
|||
*.pyc
|
||||
*.o
|
||||
*.so
|
||||
.project
|
||||
.pydevproject
|
||||
target.cfg
|
||||
target.cfg.d
|
||||
.tox
|
||||
|
||||
build/
|
||||
dist/
|
||||
*.egg-info
|
||||
wsproxy
|
||||
*.DS_Store
|
||||
|
|
|
|||
139
CHANGES.txt
139
CHANGES.txt
|
|
@ -1,139 +0,0 @@
|
|||
Changes
|
||||
=======
|
||||
|
||||
0.13.0
|
||||
------
|
||||
|
||||
* Support for Python < 3.6 has been dropped.
|
||||
* SNI is enabled when connecting to an SSL target as an SSL client.
|
||||
* The TokenRedis plugin handles namespaces.
|
||||
* Headers are sanitized before being passed to authentication plugins.
|
||||
|
||||
0.12.0
|
||||
------
|
||||
|
||||
* The simplejson module is no longer needed for redis token support
|
||||
* redis tokens can now be either JSON or plain text
|
||||
* websockify can now listen to a Unix socket for incoming connections
|
||||
|
||||
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.
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
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 +0,0 @@
|
|||
include CHANGES.txt README.md COPYING
|
||||
11
Makefile
11
Makefile
|
|
@ -1,11 +0,0 @@
|
|||
TARGETS=rebind.so
|
||||
CFLAGS += -fPIC
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
rebind.so: rebind.o
|
||||
$(CC) $(LDFLAGS) $^ -shared -fPIC -ldl -o $@
|
||||
|
||||
clean:
|
||||
rm -f rebind.o rebind.so
|
||||
|
||||
386
README.md
386
README.md
|
|
@ -1,208 +1,242 @@
|
|||
## websockify: WebSockets support for any application/server
|
||||
## noVNC: HTML5 VNC Client
|
||||
|
||||
websockify was formerly named wsproxy and was part of the
|
||||
[noVNC](https://github.com/novnc/noVNC) project.
|
||||
|
||||
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.
|
||||
### Description
|
||||
|
||||
### News/help/contact
|
||||
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).
|
||||
|
||||
Notable commits, announcements and news are posted to
|
||||
<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.
|
||||
@<a href="http://www.twitter.com/noVNC">noVNC</a>
|
||||
|
||||
|
||||
### Encrypted WebSocket connections (wss://)
|
||||
### Screenshots
|
||||
|
||||
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:
|
||||
Running in Chrome before and after connecting:
|
||||
|
||||
```
|
||||
openssl req -new -x509 -days 365 -nodes -out self.pem -keyout self.pem
|
||||
```
|
||||
<img src="http://kanaka.github.com/noVNC/img/noVNC-1.jpg" width=400> <img src="http://kanaka.github.com/noVNC/img/noVNC-2.jpg" width=400>
|
||||
|
||||
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.
|
||||
|
||||
The ports may be considered as distinguishing connections by the browser,
|
||||
for example, if your website url is https://my.local:8443 and your WebSocket
|
||||
url is wss://my.local:8001, first browse to https://my.local:8001, add the
|
||||
exception, then browse to https://my.local:8443 and add another exception.
|
||||
Then an html page served over :8443 will be able to open WSS to :8001
|
||||
|
||||
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.
|
||||
See more screenshots <a href="http://kanaka.github.com/noVNC/screenshots.html">here</a>.
|
||||
|
||||
|
||||
### Additional websockify features
|
||||
### Requirements
|
||||
|
||||
These are not necessary for the basic operation.
|
||||
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://").
|
||||
|
||||
* Daemonizing: When the `-D` option is specified, websockify runs
|
||||
in the background as a daemon process.
|
||||
There a few reasons why a proxy is required:
|
||||
|
||||
* 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).
|
||||
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').
|
||||
|
||||
* 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.
|
||||
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.
|
||||
|
||||
|
||||
### Wrap a Program
|
||||
### Quick Start
|
||||
|
||||
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.
|
||||
* 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:
|
||||
|
||||
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.
|
||||
`./utils/launch.sh --vnc localhost:5901`
|
||||
|
||||
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).
|
||||
* 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!
|
||||
|
||||
|
||||
### Installing websockify
|
||||
### Advanced usage
|
||||
|
||||
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`.
|
||||
* 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:
|
||||
|
||||
Afterwards, websockify should be available in your path. Run
|
||||
`websockify --help` to confirm it's installed correctly.
|
||||
`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.
|
||||
|
||||
|
||||
### Running with Docker/Podman
|
||||
You can also run websockify using Docker, Podman, Singularity, udocker or
|
||||
your favourite container runtime that support OCI container images.
|
||||
### Browser Support
|
||||
|
||||
The entrypoint of the image is the `run` command.
|
||||
In the following table Jaunty is Ubuntu 9.04 and WinXP is Windows XP.
|
||||
|
||||
To build the image:
|
||||
```
|
||||
./docker/build.sh
|
||||
```
|
||||
#### Linux (Ubuntu 9.04)
|
||||
|
||||
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>
|
||||
```
|
||||
<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>
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
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
|
||||
```
|
||||
* 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.
|
||||
|
|
|
|||
|
|
@ -1,61 +0,0 @@
|
|||
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.
|
||||
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
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"]
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
set -e -x
|
||||
cd "$(dirname "$0")"
|
||||
(cd .. && python3 setup.py sdist --dist-dir docker/)
|
||||
docker build -t novnc/websockify .
|
||||
|
|
@ -0,0 +1,621 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
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.
|
||||
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
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
|
||||
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
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.
|
||||
48
docs/notes
48
docs/notes
|
|
@ -1,6 +1,44 @@
|
|||
Building release tarball:
|
||||
- not really necessary since tagged revision can be downloaded
|
||||
from github as tarballs
|
||||
Some implementation notes:
|
||||
|
||||
git archive --format=tar --prefix=websockify-${WVER}/ v${WVER} > websockify-${WVER}.tar
|
||||
gzip websockify-${WVER}.tar
|
||||
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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
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).
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
- 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
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
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.
|
|
@ -1,110 +0,0 @@
|
|||
.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/
|
||||
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
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.
|
||||
*/
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
= 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,
|
||||
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
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.
|
|
@ -0,0 +1,109 @@
|
|||
<!--
|
||||
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.
Binary file not shown.
|
|
@ -0,0 +1,14 @@
|
|||
#!/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)
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
#!/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.
|
After Width: | Height: | Size: 16 KiB |
|
|
@ -0,0 +1,287 @@
|
|||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
3235
include/as3crypto_patched/src/com/hurlant/crypto/cert/MozillaRootCertificates.as
Executable file
3235
include/as3crypto_patched/src/com/hurlant/crypto/cert/MozillaRootCertificates.as
Executable file
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,218 @@
|
|||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* 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];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,368 @@
|
|||
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
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
K 14
|
||||
svn:executable
|
||||
V 1
|
||||
*
|
||||
END
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
K 14
|
||||
svn:executable
|
||||
V 1
|
||||
*
|
||||
END
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* 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;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* 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;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,339 @@
|
|||
/**
|
||||
* 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
|
|
@ -0,0 +1,375 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,365 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* 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
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* 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 {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
/**
|
||||
* 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";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#!/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
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* 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");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* 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));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
* 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue