Removing unneeded dependencies.

This commit is contained in:
Samuel Clay 2013-07-12 13:46:13 -07:00
parent 9fb183f4ac
commit 6110dc833a
264 changed files with 0 additions and 270447 deletions

File diff suppressed because one or more lines are too long

View file

@ -1,2 +0,0 @@
test/node_modules
support

View file

@ -1,226 +0,0 @@
0.9.11 / 2012-11-02
===================
* Enable use of 'xhr' transport in Node.js
* Fix the problem with disconnecting xhr-polling users
* Add should to devDependencies
* Prefer XmlHttpRequest if CORS is available
* Make client compatible with AMD loaders.
0.9.10 / 2012-08-10
===================
* fix removeAllListeners to behave as expected.
* set withCredentials to true only if xdomain.
* socket: disable disconnect on unload by default.
0.9.9 / 2012-08-01
==================
* socket: fixed disconnect xhr url and made it actually sync
* *: bump xmlhttprequest dep
0.9.8 / 2012-07-24
==================
* Fixed build.
0.9.7 / 2012-07-24
==================
* iOS websocket crash fix.
* Fixed potential `open` collision.
* Fixed disconnectSync.
0.9.6 / 2012-04-17
==================
* Don't position the jsonp form off the screen (android fix).
0.9.5 / 2012-04-05
==================
* Bumped version.
0.9.4 / 2012-04-01
==================
* Fixes polling loop upon reconnect advice (fixes #438).
0.9.3 / 2012-03-28
==================
* Fix XHR.check, which was throwing an error transparently and causing non-IE browsers to fall back to JSONP [mikito]
* Fixed forced disconnect on window close [zzzaaa]
0.9.2 / 2012-03-13
==================
* Transport order set by "options" [zzzaaa]
0.9.1-1 / 2012-03-02
====================
* Fixed active-x-obfuscator NPM dependency.
0.9.1 / 2012-03-02
==================
* Misc corrections.
* Added warning within Firefox about webworker test in test runner.
* Update ws dependency [einaros]
* Implemented client side heartbeat checks. [felixge]
* Improved Firewall support with ActiveX obfuscation. [felixge]
* Fixed error handling during connection process. [Outsideris]
0.9.0 / 2012-02-26
==================
* Added DS_Store to gitignore.
* Updated depedencies.
* Bumped uglify
* Tweaking code so it doesn't throw an exception when used inside a WebWorker in Firefox
* Do not rely on Array.prototype.indexOf as it breaks with pages that use the Prototype.js library.
* Windows support landed
* Use @einaros ws module instead of the old crap one
* Fix for broken closeTimeout and 'IE + xhr' goes into infinite loop on disconnection
* Disabled reconnection on error if reconnect option is set to false
* Set withCredentials to true before xhr to fix authentication
* Clears the timeout from reconnection attempt when there is a successful or failed reconnection.
This fixes the issue of setTimeout's carrying over from previous reconnection
and changing (skipping) values of self.reconnectionDelay in the newer reconnection.
* Removed decoding of parameters when chunking the query string.
This was used later on to construct the url to post to the socket.io server
for connection and if we're adding custom parameters of our own to this url
(for example for OAuth authentication) they were being sent decoded, which is wrong.
0.8.7 / 2011-11-05
==================
* Bumped client
0.8.6 / 2011-10-27
==================
* Added WebWorker support.
* Fixed swfobject and web_socket.js to not assume window.
* Fixed CORS detection for webworker.
* Fix `defer` for webkit in a webworker.
* Fixed io.util.request to not rely on window.
* FIxed; use global instead of window and dont rely on document.
* Fixed; JSON-P handshake if CORS is not available.
* Made underlying Transport disconnection trigger immediate socket.io disconnect.
* Fixed warning when compressing with Google Closure Compiler.
* Fixed builder's uglify utf-8 support.
* Added workaround for loading indicator in FF jsonp-polling. [3rd-Eden]
* Fixed host discovery lookup. [holic]
* Fixed close timeout when disconnected/reconnecting. [jscharlach]
* Fixed jsonp-polling feature detection.
* Fixed jsonp-polling client POSTing of \n.
* Fixed test runner on IE6/7
0.8.5 / 2011-10-07
==================
* Bumped client
0.8.4 / 2011-09-06
==================
* Corrected build
0.8.3 / 2011-09-03
==================
* Fixed `\n` parsing for non-JSON packets.
* Fixed; make Socket.IO XHTML doctype compatible (fixes #460 from server)
* Fixed support for Node.JS running `socket.io-client`.
* Updated repository name in `package.json`.
* Added support for different policy file ports without having to port
forward 843 on the server side [3rd-Eden]
0.8.2 / 2011-08-29
==================
* Fixed flashsocket detection.
0.8.1 / 2011-08-29
==================
* Bump version.
0.8.0 / 2011-08-28
==================
* Added MozWebSocket support (hybi-10 doesn't require API changes) [einaros].
0.7.11 / 2011-08-27
===================
* Corrected previous release (missing build).
0.7.10 / 2011-08-27
===================
* Fix for failing fallback in websockets
0.7.9 / 2011-08-12
==================
* Added check on `Socket#onConnect` to prevent double `connect` events on the main manager.
* Fixed socket namespace connect test. Remove broken alternative namespace connect test.
* Removed test handler for removed test.
* Bumped version to match `socket.io` server.
0.7.5 / 2011-08-08
==================
* Added querystring support for `connect` [3rd-Eden]
* Added partial Node.JS transports support [3rd-Eden, josephg]
* Fixed builder test.
* Changed `util.inherit` to replicate Object.create / __proto__.
* Changed and cleaned up some acceptance tests.
* Fixed race condition with a test that could not be run multiple times.
* Added test for encoding a payload.
* Added the ability to override the transport to use in acceptance test [3rd-Eden]
* Fixed multiple connect packets [DanielBaulig]
* Fixed jsonp-polling over-buffering [3rd-Eden]
* Fixed ascii preservation in minified socket.io client [3rd-Eden]
* Fixed socket.io in situations where the page is not served through utf8.
* Fixed namespaces not reconnecting after disconnect [3rd-Eden]
* Fixed default port for secure connections.
0.7.4 / 2011-07-12
==================
* Added `SocketNamespace#of` shortcut. [3rd-Eden]
* Fixed a IE payload decoding bug. [3rd-Eden]
* Honor document protocol, unless overriden. [dvv]
* Fixed new builder dependencies. [3rd-Eden]
0.7.3 / 2011-06-30
==================
* Fixed; acks don't depend on arity. They're automatic for `.send` and
callback based for `.emit`. [dvv]
* Added support for sub-sockets authorization. [3rd-Eden]
* Added BC support for `new io.connect`. [fat]
* Fixed double `connect` events. [3rd-Eden]
* Fixed reconnection with jsonp-polling maintaining old sessionid. [franck34]
0.7.2 / 2011-06-22
==================
* Added `noop` message type.
0.7.1 / 2011-06-21
==================
* Bumped socket.io dependency version for acceptance tests.
0.7.0 / 2011-06-21
==================
* http://socket.io/announcement.html

View file

@ -1,20 +0,0 @@
ALL_TESTS = $(shell find test/ -name '*.test.js')
run-tests:
@./node_modules/.bin/expresso \
-I lib \
-I support \
--serial \
$(TESTS)
test:
@$(MAKE) TESTS="$(ALL_TESTS)" run-tests
test-acceptance:
@node support/test-runner/app $(TRANSPORT)
build:
@node ./bin/builder.js
.PHONY: test

View file

@ -1,246 +0,0 @@
socket.io
=========
#### Sockets for the rest of us
The `socket.io` client is basically a simple HTTP Socket interface implementation.
It looks similar to WebSocket while providing additional features and
leveraging other transports when WebSocket is not supported by the user's
browser.
```js
var socket = io.connect('http://domain.com');
socket.on('connect', function () {
// socket connected
});
socket.on('custom event', function () {
// server emitted a custom event
});
socket.on('disconnect', function () {
// socket disconnected
});
socket.send('hi there');
```
### Recipes
#### Utilizing namespaces (ie: multiple sockets)
If you want to namespace all the messages and events emitted to a particular
endpoint, simply specify it as part of the `connect` uri:
```js
var chat = io.connect('http://localhost/chat');
chat.on('connect', function () {
// chat socket connected
});
var news = io.connect('/news'); // io.connect auto-detects host
news.on('connect', function () {
// news socket connected
});
```
#### Emitting custom events
To ease with the creation of applications, you can emit custom events outside
of the global `message` event.
```js
var socket = io.connect();
socket.emit('server custom event', { my: 'data' });
```
#### Forcing disconnection
```js
var socket = io.connect();
socket.on('connect', function () {
socket.disconnect();
});
```
### Documentation
#### io#connect
```js
io.connect(uri, [options]);
```
##### Options:
- *resource*
socket.io
The resource is what allows the `socket.io` server to identify incoming connections by `socket.io` clients. In other words, any HTTP server can implement socket.io and still serve other normal, non-realtime HTTP requests.
- *transports*
```js
['websocket', 'flashsocket', 'htmlfile', 'xhr-multipart', 'xhr-polling', 'jsonp-polling']
```
A list of the transports to attempt to utilize (in order of preference).
- *'connect timeout'*
```js
5000
```
The amount of milliseconds a transport has to create a connection before we consider it timed out.
- *'try multiple transports'*
```js
true
```
A boolean indicating if we should try other transports when the connectTimeout occurs.
- *reconnect*
```js
true
```
A boolean indicating if we should automatically reconnect if a connection is disconnected.
- *'reconnection delay'*
```js
500
```
The amount of milliseconds before we try to connect to the server again. We are using a exponential back off algorithm for the following reconnections, on each reconnect attempt this value will get multiplied (500 > 1000 > 2000 > 4000 > 8000).
- *'max reconnection attempts'*
```js
10
```
The amount of attempts should we make using the current transport to connect to the server? After this we will do one final attempt, and re-try with all enabled transport methods before we give up.
##### Properties:
- *options*
The passed in options combined with the defaults.
- *connected*
Whether the socket is connected or not.
- *connecting*
Whether the socket is connecting or not.
- *reconnecting*
Whether we are reconnecting or not.
- *transport*
The transport instance.
##### Methods:
- *connect(λ)*
Establishes a connection. If λ is supplied as argument, it will be called once the connection is established.
- *send(message)*
A string of data to send.
- *disconnect*
Closes the connection.
- *on(event, λ)*
Adds a listener for the event *event*.
- *once(event, λ)*
Adds a one time listener for the event *event*. The listener is removed after the first time the event is fired.
- *removeListener(event, λ)*
Removes the listener λ for the event *event*.
##### Events:
- *connect*
Fired when the connection is established and the handshake successful.
- *connecting(transport_type)*
Fired when a connection is attempted, passing the transport name.
- *connect_failed*
Fired when the connection timeout occurs after the last connection attempt.
This only fires if the `connectTimeout` option is set.
If the `tryTransportsOnConnectTimeout` option is set, this only fires once all
possible transports have been tried.
- *message(message)*
Fired when a message arrives from the server
- *close*
Fired when the connection is closed. Be careful with using this event, as some transports will fire it even under temporary, expected disconnections (such as XHR-Polling).
- *disconnect*
Fired when the connection is considered disconnected.
- *reconnect(transport_type,reconnectionAttempts)*
Fired when the connection has been re-established. This only fires if the `reconnect` option is set.
- *reconnecting(reconnectionDelay,reconnectionAttempts)*
Fired when a reconnection is attempted, passing the next delay for the next reconnection.
- *reconnect_failed*
Fired when all reconnection attempts have failed and we where unsuccessful in reconnecting to the server.
### Contributors
Guillermo Rauch <guillermo@learnboost.com>
Arnout Kazemier <info@3rd-eden.com>
### License
(The MIT License)
Copyright (c) 2010 LearnBoost <dev@learnboost.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,303 +0,0 @@
/*!
* socket.io-node
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var fs = require('fs')
, socket = require('../lib/io')
, uglify = require('uglify-js')
, activeXObfuscator = require('active-x-obfuscator');
/**
* License headers.
*
* @api private
*/
var template = '/*! Socket.IO.%ext% build:' + socket.version + ', %type%. Copyright(c) 2011 LearnBoost <dev@learnboost.com> MIT Licensed */\n'
, development = template.replace('%type%', 'development').replace('%ext%', 'js')
, production = template.replace('%type%', 'production').replace('%ext%', 'min.js');
/**
* If statements, these allows you to create serveride & client side compatible
* code using specially designed `if` statements that remove serverside
* designed code from the source files
*
* @api private
*/
var starttagIF = '// if node'
, endtagIF = '// end node';
/**
* The modules that are required to create a base build of Socket.IO.
*
* @const
* @type {Array}
* @api private
*/
var base = [
'io.js'
, 'util.js'
, 'events.js'
, 'json.js'
, 'parser.js'
, 'transport.js'
, 'socket.js'
, 'namespace.js'
];
/**
* The available transports for Socket.IO. These are mapped as:
*
* - `key` the name of the transport
* - `value` the dependencies for the transport
*
* @const
* @type {Object}
* @api public
*/
var baseTransports = {
'websocket': ['transports/websocket.js']
, 'flashsocket': [
'transports/websocket.js'
, 'transports/flashsocket.js'
, 'vendor/web-socket-js/swfobject.js'
, 'vendor/web-socket-js/web_socket.js'
]
, 'htmlfile': ['transports/xhr.js', 'transports/htmlfile.js']
/* FIXME: re-enable me once we have multi-part support
, 'xhr-multipart': ['transports/xhr.js', 'transports/xhr-multipart.js'] */
, 'xhr-polling': ['transports/xhr.js', 'transports/xhr-polling.js']
, 'jsonp-polling': [
'transports/xhr.js'
, 'transports/xhr-polling.js'
, 'transports/jsonp-polling.js'
]
};
/**
* Wrappers for client-side usage.
* This enables usage in top-level browser window, client-side CommonJS systems and AMD loaders.
* If doing a node build for server-side client, this wrapper is NOT included.
* @api private
*/
var wrapperPre = "\nvar io = ('undefined' === typeof module ? {} : module.exports);\n(function() {\n";
var wrapperPost = "\nif (typeof define === \"function\" && define.amd) {" +
"\n define([], function () { return io; });" +
"\n}\n})();";
/**
* Builds a custom Socket.IO distribution based on the transports that you
* need. You can configure the build to create development build or production
* build (minified).
*
* @param {Array} transports The transports that needs to be bundled.
* @param {Object} [options] Options to configure the building process.
* @param {Function} callback Last argument should always be the callback
* @callback {String|Boolean} err An optional argument, if it exists than an error
* occurred during the build process.
* @callback {String} result The result of the build process.
* @api public
*/
var builder = module.exports = function () {
var transports, options, callback, error = null
, args = Array.prototype.slice.call(arguments, 0)
, settings = {
minify: true
, node: false
, custom: []
};
// Fancy pancy argument support this makes any pattern possible mainly
// because we require only one of each type
args.forEach(function (arg) {
var type = Object.prototype.toString.call(arg)
.replace(/\[object\s(\w+)\]/gi , '$1' ).toLowerCase();
switch (type) {
case 'array':
return transports = arg;
case 'object':
return options = arg;
case 'function':
return callback = arg;
}
});
// Add defaults
options = options || {};
transports = transports || Object.keys(baseTransports);
// Merge the data
for(var option in options) {
settings[option] = options[option];
}
// Start creating a dependencies chain with all the required files for the
// custom Socket.IO bundle.
var files = [];
base.forEach(function (file) {
files.push(__dirname + '/../lib/' + file);
});
transports.forEach(function (transport) {
var dependencies = baseTransports[transport];
if (!dependencies) {
error = 'Unsupported transport `' + transport + '` supplied as argument.';
return;
}
// Add the files to the files list, but only if they are not added before
dependencies.forEach(function (file) {
var path = __dirname + '/../lib/' + file;
if (!~files.indexOf(path)) files.push(path);
})
});
// check to see if the files tree compilation generated any errors.
if (error) return callback(error);
var results = {};
files.forEach(function (file) {
fs.readFile(file, function (err, content) {
if (err) error = err;
results[file] = content;
// check if we are done yet, or not.. Just by checking the size of the result
// object.
if (Object.keys(results).length !== files.length) return;
// we are done, did we error?
if (error) return callback(error);
// start with the license header
var code = development
, ignore = 0;
// pre-wrapper for non-server-side builds
if (!settings.node) code += wrapperPre;
// concatenate the file contents in order
files.forEach(function (file) {
code += results[file];
});
// check if we need to add custom code
if (settings.custom.length) {
settings.custom.forEach(function (content) {
code += content;
});
}
// post-wrapper for non-server-side builds
if (!settings.node) {
code += wrapperPost;
}
code = activeXObfuscator(code);
// Search for conditional code blocks that need to be removed as they
// where designed for a server side env. but only if we don't want to
// make this build node compatible.
if (!settings.node) {
code = code.split('\n').filter(function (line) {
// check if there are tags in here
var start = line.indexOf(starttagIF) >= 0
, end = line.indexOf(endtagIF) >= 0
, ret = ignore;
// ignore the current line
if (start) {
ignore++;
ret = ignore;
}
// stop ignoring the next line
if (end) {
ignore--;
}
return ret == 0;
}).join('\n');
}
// check if we need to process it any further
if (settings.minify) {
var ast = uglify.parser.parse(code);
ast = uglify.uglify.ast_mangle(ast);
ast = uglify.uglify.ast_squeeze(ast);
code = production + uglify.uglify.gen_code(ast, { ascii_only: true });
}
callback(error, code);
})
})
};
/**
* Builder version is also the current client version
* this way we don't have to do another include for the
* clients version number and we can just include the builder.
*
* @type {String}
* @api public
*/
builder.version = socket.version;
/**
* A list of all build in transport types.
*
* @type {Object}
* @api public
*/
builder.transports = baseTransports;
/**
* Command line support, this allows us to generate builds without having
* to load it as module.
*/
if (!module.parent){
// the first 2 are `node` and the path to this file, we don't need them
var args = process.argv.slice(2);
// build a development build
builder(args.length ? args : false, { minify:false }, function (err, content) {
if (err) return console.error(err);
fs.write(
fs.openSync(__dirname + '/../dist/socket.io.js', 'w')
, content
, 0
, 'utf8'
);
console.log('Successfully generated the development build: socket.io.js');
});
// and build a production build
builder(args.length ? args : false, function (err, content) {
if (err) return console.error(err);
fs.write(
fs.openSync(__dirname + '/../dist/socket.io.min.js', 'w')
, content
, 0
, 'utf8'
);
console.log('Successfully generated the production build: socket.io.min.js');
});
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,182 +0,0 @@
/**
* socket.io
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
(function (exports, io) {
/**
* Expose constructor.
*/
exports.EventEmitter = EventEmitter;
/**
* Event emitter constructor.
*
* @api public.
*/
function EventEmitter () {};
/**
* Adds a listener
*
* @api public
*/
EventEmitter.prototype.on = function (name, fn) {
if (!this.$events) {
this.$events = {};
}
if (!this.$events[name]) {
this.$events[name] = fn;
} else if (io.util.isArray(this.$events[name])) {
this.$events[name].push(fn);
} else {
this.$events[name] = [this.$events[name], fn];
}
return this;
};
EventEmitter.prototype.addListener = EventEmitter.prototype.on;
/**
* Adds a volatile listener.
*
* @api public
*/
EventEmitter.prototype.once = function (name, fn) {
var self = this;
function on () {
self.removeListener(name, on);
fn.apply(this, arguments);
};
on.listener = fn;
this.on(name, on);
return this;
};
/**
* Removes a listener.
*
* @api public
*/
EventEmitter.prototype.removeListener = function (name, fn) {
if (this.$events && this.$events[name]) {
var list = this.$events[name];
if (io.util.isArray(list)) {
var pos = -1;
for (var i = 0, l = list.length; i < l; i++) {
if (list[i] === fn || (list[i].listener && list[i].listener === fn)) {
pos = i;
break;
}
}
if (pos < 0) {
return this;
}
list.splice(pos, 1);
if (!list.length) {
delete this.$events[name];
}
} else if (list === fn || (list.listener && list.listener === fn)) {
delete this.$events[name];
}
}
return this;
};
/**
* Removes all listeners for an event.
*
* @api public
*/
EventEmitter.prototype.removeAllListeners = function (name) {
if (name === undefined) {
this.$events = {};
return this;
}
if (this.$events && this.$events[name]) {
this.$events[name] = null;
}
return this;
};
/**
* Gets all listeners for a certain event.
*
* @api publci
*/
EventEmitter.prototype.listeners = function (name) {
if (!this.$events) {
this.$events = {};
}
if (!this.$events[name]) {
this.$events[name] = [];
}
if (!io.util.isArray(this.$events[name])) {
this.$events[name] = [this.$events[name]];
}
return this.$events[name];
};
/**
* Emits an event.
*
* @api public
*/
EventEmitter.prototype.emit = function (name) {
if (!this.$events) {
return false;
}
var handler = this.$events[name];
if (!handler) {
return false;
}
var args = Array.prototype.slice.call(arguments, 1);
if ('function' == typeof handler) {
handler.apply(this, args);
} else if (io.util.isArray(handler)) {
var listeners = handler.slice();
for (var i = 0, l = listeners.length; i < l; i++) {
listeners[i].apply(this, args);
}
} else {
return false;
}
return true;
};
})(
'undefined' != typeof io ? io : module.exports
, 'undefined' != typeof io ? io : module.parent.exports
);

View file

@ -1,206 +0,0 @@
/**
* socket.io
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
(function (exports, global) {
/**
* IO namespace.
*
* @namespace
*/
var io = exports;
/**
* Socket.IO version
*
* @api public
*/
io.version = '0.9.11';
/**
* Protocol implemented.
*
* @api public
*/
io.protocol = 1;
/**
* Available transports, these will be populated with the available transports
*
* @api public
*/
io.transports = [];
/**
* Keep track of jsonp callbacks.
*
* @api private
*/
io.j = [];
/**
* Keep track of our io.Sockets
*
* @api private
*/
io.sockets = {};
// if node
/**
* Expose constructors if in Node
*/
if ('object' === typeof module && 'function' === typeof require) {
/**
* Expose utils
*
* @api private
*/
io.util = require('./util').util;
/**
* Expose JSON.
*
* @api private
*/
io.JSON = require('./json').JSON;
/**
* Expose parser.
*
* @api private
*/
io.parser = require('./parser').parser;
/**
* Expose EventEmitter
*
* @api private
*/
io.EventEmitter = require('./events').EventEmitter;
/**
* Expose SocketNamespace
*
* @api private
*/
io.SocketNamespace = require('./namespace').SocketNamespace;
/**
* Expose Transport
*
* @api public
*/
io.Transport = require('./transport').Transport;
/**
* Default enabled transports
*
* @api public
*/
io.transports = ['websocket', 'xhr-polling'];
/**
* Expose all transports
*
* @api public
*/
io.Transport.XHR = require('./transports/xhr').XHR;
io.transports.forEach(function (t) {
io.Transport[t] = require('./transports/' + t)[t];
});
/**
* Expose Socket
*
* @api public
*/
io.Socket = require('./socket').Socket;
/**
* Location of `dist/` directory.
*
* @api private
*/
io.dist = __dirname + '/../dist';
/**
* Expose our build system which can generate
* socket.io files on the fly with different transports
*
* @api private
*/
io.builder = require('../bin/builder');
}
// end node
/**
* Manages connections to hosts.
*
* @param {String} uri
* @Param {Boolean} force creation of new socket (defaults to false)
* @api public
*/
io.connect = function (host, details) {
var uri = io.util.parseUri(host)
, uuri
, socket;
if (global && global.location) {
uri.protocol = uri.protocol || global.location.protocol.slice(0, -1);
uri.host = uri.host || (global.document
? global.document.domain : global.location.hostname);
uri.port = uri.port || global.location.port;
}
uuri = io.util.uniqueUri(uri);
var options = {
host: uri.host
, secure: 'https' == uri.protocol
, port: uri.port || ('https' == uri.protocol ? 443 : 80)
, query: uri.query || ''
};
io.util.merge(options, details);
if (options['force new connection'] || !io.sockets[uuri]) {
socket = new io.Socket(options);
}
if (!options['force new connection'] && socket) {
io.sockets[uuri] = socket;
}
socket = socket || io.sockets[uuri];
// if path is different from '' or /
return socket.of(uri.path.length > 1 ? uri.path : '');
};
})('object' === typeof module ? module.exports : (this.io = {}), this);

View file

@ -1,322 +0,0 @@
/**
* socket.io
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
/**
* Based on JSON2 (http://www.JSON.org/js.html).
*/
(function (exports, nativeJSON) {
"use strict";
// use native JSON if it's available
if (nativeJSON && nativeJSON.parse){
return exports.JSON = {
parse: nativeJSON.parse
, stringify: nativeJSON.stringify
};
}
var JSON = exports.JSON = {};
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
function date(d, key) {
return isFinite(d.valueOf()) ?
d.getUTCFullYear() + '-' +
f(d.getUTCMonth() + 1) + '-' +
f(d.getUTCDate()) + 'T' +
f(d.getUTCHours()) + ':' +
f(d.getUTCMinutes()) + ':' +
f(d.getUTCSeconds()) + 'Z' : null;
};
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
gap,
indent,
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
},
rep;
function quote(string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
escapable.lastIndex = 0;
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
var c = meta[a];
return typeof c === 'string' ? c :
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' : '"' + string + '"';
}
function str(key, holder) {
// Produce a string from holder[key].
var i, // The loop counter.
k, // The member key.
v, // The member value.
length,
mind = gap,
partial,
value = holder[key];
// If the value has a toJSON method, call it to obtain a replacement value.
if (value instanceof Date) {
value = date(key);
}
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
if (typeof rep === 'function') {
value = rep.call(holder, key, value);
}
// What happens next depends on the value's type.
switch (typeof value) {
case 'string':
return quote(value);
case 'number':
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : 'null';
case 'boolean':
case 'null':
// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.
return String(value);
// If the type is 'object', we might be dealing with an object or an array or
// null.
case 'object':
// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.
if (!value) {
return 'null';
}
// Make an array to hold the partial results of stringifying this object value.
gap += indent;
partial = [];
// Is the value an array?
if (Object.prototype.toString.apply(value) === '[object Array]') {
// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || 'null';
}
// Join all of the elements together, separated with commas, and wrap them in
// brackets.
v = partial.length === 0 ? '[]' : gap ?
'[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
'[' + partial.join(',') + ']';
gap = mind;
return v;
}
// If the replacer is an array, use it to select the members to be stringified.
if (rep && typeof rep === 'object') {
length = rep.length;
for (i = 0; i < length; i += 1) {
if (typeof rep[i] === 'string') {
k = rep[i];
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
} else {
// Otherwise, iterate through all of the keys in the object.
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
}
// Join all of the member texts together, separated with commas,
// and wrap them in braces.
v = partial.length === 0 ? '{}' : gap ?
'{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
'{' + partial.join(',') + '}';
gap = mind;
return v;
}
}
// If the JSON object does not yet have a stringify method, give it one.
JSON.stringify = function (value, replacer, space) {
// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.
var i;
gap = '';
indent = '';
// If the space parameter is a number, make an indent string containing that
// many spaces.
if (typeof space === 'number') {
for (i = 0; i < space; i += 1) {
indent += ' ';
}
// If the space parameter is a string, it will be used as the indent string.
} else if (typeof space === 'string') {
indent = space;
}
// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.
rep = replacer;
if (replacer && typeof replacer !== 'function' &&
(typeof replacer !== 'object' ||
typeof replacer.length !== 'number')) {
throw new Error('JSON.stringify');
}
// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.
return str('', {'': value});
};
// If the JSON object does not yet have a parse method, give it one.
JSON.parse = function (text, reviver) {
// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.
var j;
function walk(holder, key) {
// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.
var k, v, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}
// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
text = String(text);
cx.lastIndex = 0;
if (cx.test(text)) {
text = text.replace(cx, function (a) {
return '\\u' +
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.
// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
if (/^[\],:{}\s]*$/
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
j = eval('(' + text + ')');
// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.
return typeof reviver === 'function' ?
walk({'': j}, '') : j;
}
// If the text is not JSON parseable, then a SyntaxError is thrown.
throw new SyntaxError('JSON.parse');
};
})(
'undefined' != typeof io ? io : module.exports
, typeof JSON !== 'undefined' ? JSON : undefined
);

View file

@ -1,242 +0,0 @@
/**
* socket.io
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
(function (exports, io) {
/**
* Expose constructor.
*/
exports.SocketNamespace = SocketNamespace;
/**
* Socket namespace constructor.
*
* @constructor
* @api public
*/
function SocketNamespace (socket, name) {
this.socket = socket;
this.name = name || '';
this.flags = {};
this.json = new Flag(this, 'json');
this.ackPackets = 0;
this.acks = {};
};
/**
* Apply EventEmitter mixin.
*/
io.util.mixin(SocketNamespace, io.EventEmitter);
/**
* Copies emit since we override it
*
* @api private
*/
SocketNamespace.prototype.$emit = io.EventEmitter.prototype.emit;
/**
* Creates a new namespace, by proxying the request to the socket. This
* allows us to use the synax as we do on the server.
*
* @api public
*/
SocketNamespace.prototype.of = function () {
return this.socket.of.apply(this.socket, arguments);
};
/**
* Sends a packet.
*
* @api private
*/
SocketNamespace.prototype.packet = function (packet) {
packet.endpoint = this.name;
this.socket.packet(packet);
this.flags = {};
return this;
};
/**
* Sends a message
*
* @api public
*/
SocketNamespace.prototype.send = function (data, fn) {
var packet = {
type: this.flags.json ? 'json' : 'message'
, data: data
};
if ('function' == typeof fn) {
packet.id = ++this.ackPackets;
packet.ack = true;
this.acks[packet.id] = fn;
}
return this.packet(packet);
};
/**
* Emits an event
*
* @api public
*/
SocketNamespace.prototype.emit = function (name) {
var args = Array.prototype.slice.call(arguments, 1)
, lastArg = args[args.length - 1]
, packet = {
type: 'event'
, name: name
};
if ('function' == typeof lastArg) {
packet.id = ++this.ackPackets;
packet.ack = 'data';
this.acks[packet.id] = lastArg;
args = args.slice(0, args.length - 1);
}
packet.args = args;
return this.packet(packet);
};
/**
* Disconnects the namespace
*
* @api private
*/
SocketNamespace.prototype.disconnect = function () {
if (this.name === '') {
this.socket.disconnect();
} else {
this.packet({ type: 'disconnect' });
this.$emit('disconnect');
}
return this;
};
/**
* Handles a packet
*
* @api private
*/
SocketNamespace.prototype.onPacket = function (packet) {
var self = this;
function ack () {
self.packet({
type: 'ack'
, args: io.util.toArray(arguments)
, ackId: packet.id
});
};
switch (packet.type) {
case 'connect':
this.$emit('connect');
break;
case 'disconnect':
if (this.name === '') {
this.socket.onDisconnect(packet.reason || 'booted');
} else {
this.$emit('disconnect', packet.reason);
}
break;
case 'message':
case 'json':
var params = ['message', packet.data];
if (packet.ack == 'data') {
params.push(ack);
} else if (packet.ack) {
this.packet({ type: 'ack', ackId: packet.id });
}
this.$emit.apply(this, params);
break;
case 'event':
var params = [packet.name].concat(packet.args);
if (packet.ack == 'data')
params.push(ack);
this.$emit.apply(this, params);
break;
case 'ack':
if (this.acks[packet.ackId]) {
this.acks[packet.ackId].apply(this, packet.args);
delete this.acks[packet.ackId];
}
break;
case 'error':
if (packet.advice){
this.socket.onError(packet);
} else {
if (packet.reason == 'unauthorized') {
this.$emit('connect_failed', packet.reason);
} else {
this.$emit('error', packet.reason);
}
}
break;
}
};
/**
* Flag interface.
*
* @api private
*/
function Flag (nsp, name) {
this.namespace = nsp;
this.name = name;
};
/**
* Send a message
*
* @api public
*/
Flag.prototype.send = function () {
this.namespace.flags[this.name] = true;
this.namespace.send.apply(this.namespace, arguments);
};
/**
* Emit an event
*
* @api public
*/
Flag.prototype.emit = function () {
this.namespace.flags[this.name] = true;
this.namespace.emit.apply(this.namespace, arguments);
};
})(
'undefined' != typeof io ? io : module.exports
, 'undefined' != typeof io ? io : module.parent.exports
);

View file

@ -1,262 +0,0 @@
/**
* socket.io
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
(function (exports, io) {
/**
* Parser namespace.
*
* @namespace
*/
var parser = exports.parser = {};
/**
* Packet types.
*/
var packets = parser.packets = [
'disconnect'
, 'connect'
, 'heartbeat'
, 'message'
, 'json'
, 'event'
, 'ack'
, 'error'
, 'noop'
];
/**
* Errors reasons.
*/
var reasons = parser.reasons = [
'transport not supported'
, 'client not handshaken'
, 'unauthorized'
];
/**
* Errors advice.
*/
var advice = parser.advice = [
'reconnect'
];
/**
* Shortcuts.
*/
var JSON = io.JSON
, indexOf = io.util.indexOf;
/**
* Encodes a packet.
*
* @api private
*/
parser.encodePacket = function (packet) {
var type = indexOf(packets, packet.type)
, id = packet.id || ''
, endpoint = packet.endpoint || ''
, ack = packet.ack
, data = null;
switch (packet.type) {
case 'error':
var reason = packet.reason ? indexOf(reasons, packet.reason) : ''
, adv = packet.advice ? indexOf(advice, packet.advice) : '';
if (reason !== '' || adv !== '')
data = reason + (adv !== '' ? ('+' + adv) : '');
break;
case 'message':
if (packet.data !== '')
data = packet.data;
break;
case 'event':
var ev = { name: packet.name };
if (packet.args && packet.args.length) {
ev.args = packet.args;
}
data = JSON.stringify(ev);
break;
case 'json':
data = JSON.stringify(packet.data);
break;
case 'connect':
if (packet.qs)
data = packet.qs;
break;
case 'ack':
data = packet.ackId
+ (packet.args && packet.args.length
? '+' + JSON.stringify(packet.args) : '');
break;
}
// construct packet with required fragments
var encoded = [
type
, id + (ack == 'data' ? '+' : '')
, endpoint
];
// data fragment is optional
if (data !== null && data !== undefined)
encoded.push(data);
return encoded.join(':');
};
/**
* Encodes multiple messages (payload).
*
* @param {Array} messages
* @api private
*/
parser.encodePayload = function (packets) {
var decoded = '';
if (packets.length == 1)
return packets[0];
for (var i = 0, l = packets.length; i < l; i++) {
var packet = packets[i];
decoded += '\ufffd' + packet.length + '\ufffd' + packets[i];
}
return decoded;
};
/**
* Decodes a packet
*
* @api private
*/
var regexp = /([^:]+):([0-9]+)?(\+)?:([^:]+)?:?([\s\S]*)?/;
parser.decodePacket = function (data) {
var pieces = data.match(regexp);
if (!pieces) return {};
var id = pieces[2] || ''
, data = pieces[5] || ''
, packet = {
type: packets[pieces[1]]
, endpoint: pieces[4] || ''
};
// whether we need to acknowledge the packet
if (id) {
packet.id = id;
if (pieces[3])
packet.ack = 'data';
else
packet.ack = true;
}
// handle different packet types
switch (packet.type) {
case 'error':
var pieces = data.split('+');
packet.reason = reasons[pieces[0]] || '';
packet.advice = advice[pieces[1]] || '';
break;
case 'message':
packet.data = data || '';
break;
case 'event':
try {
var opts = JSON.parse(data);
packet.name = opts.name;
packet.args = opts.args;
} catch (e) { }
packet.args = packet.args || [];
break;
case 'json':
try {
packet.data = JSON.parse(data);
} catch (e) { }
break;
case 'connect':
packet.qs = data || '';
break;
case 'ack':
var pieces = data.match(/^([0-9]+)(\+)?(.*)/);
if (pieces) {
packet.ackId = pieces[1];
packet.args = [];
if (pieces[3]) {
try {
packet.args = pieces[3] ? JSON.parse(pieces[3]) : [];
} catch (e) { }
}
}
break;
case 'disconnect':
case 'heartbeat':
break;
};
return packet;
};
/**
* Decodes data payload. Detects multiple messages
*
* @return {Array} messages
* @api public
*/
parser.decodePayload = function (data) {
// IE doesn't like data[i] for unicode chars, charAt works fine
if (data.charAt(0) == '\ufffd') {
var ret = [];
for (var i = 1, length = ''; i < data.length; i++) {
if (data.charAt(i) == '\ufffd') {
ret.push(parser.decodePacket(data.substr(i + 1).substr(0, length)));
i += Number(length) + 1;
length = '';
} else {
length += data.charAt(i);
}
}
return ret;
} else {
return [parser.decodePacket(data)];
}
};
})(
'undefined' != typeof io ? io : module.exports
, 'undefined' != typeof io ? io : module.parent.exports
);

View file

@ -1,579 +0,0 @@
/**
* socket.io
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
(function (exports, io, global) {
/**
* Expose constructor.
*/
exports.Socket = Socket;
/**
* Create a new `Socket.IO client` which can establish a persistent
* connection with a Socket.IO enabled server.
*
* @api public
*/
function Socket (options) {
this.options = {
port: 80
, secure: false
, document: 'document' in global ? document : false
, resource: 'socket.io'
, transports: io.transports
, 'connect timeout': 10000
, 'try multiple transports': true
, 'reconnect': true
, 'reconnection delay': 500
, 'reconnection limit': Infinity
, 'reopen delay': 3000
, 'max reconnection attempts': 10
, 'sync disconnect on unload': false
, 'auto connect': true
, 'flash policy port': 10843
, 'manualFlush': false
};
io.util.merge(this.options, options);
this.connected = false;
this.open = false;
this.connecting = false;
this.reconnecting = false;
this.namespaces = {};
this.buffer = [];
this.doBuffer = false;
if (this.options['sync disconnect on unload'] &&
(!this.isXDomain() || io.util.ua.hasCORS)) {
var self = this;
io.util.on(global, 'beforeunload', function () {
self.disconnectSync();
}, false);
}
if (this.options['auto connect']) {
this.connect();
}
};
/**
* Apply EventEmitter mixin.
*/
io.util.mixin(Socket, io.EventEmitter);
/**
* Returns a namespace listener/emitter for this socket
*
* @api public
*/
Socket.prototype.of = function (name) {
if (!this.namespaces[name]) {
this.namespaces[name] = new io.SocketNamespace(this, name);
if (name !== '') {
this.namespaces[name].packet({ type: 'connect' });
}
}
return this.namespaces[name];
};
/**
* Emits the given event to the Socket and all namespaces
*
* @api private
*/
Socket.prototype.publish = function () {
this.emit.apply(this, arguments);
var nsp;
for (var i in this.namespaces) {
if (this.namespaces.hasOwnProperty(i)) {
nsp = this.of(i);
nsp.$emit.apply(nsp, arguments);
}
}
};
/**
* Performs the handshake
*
* @api private
*/
function empty () { };
Socket.prototype.handshake = function (fn) {
var self = this
, options = this.options;
function complete (data) {
if (data instanceof Error) {
self.connecting = false;
self.onError(data.message);
} else {
fn.apply(null, data.split(':'));
}
};
var url = [
'http' + (options.secure ? 's' : '') + ':/'
, options.host + ':' + options.port
, options.resource
, io.protocol
, io.util.query(this.options.query, 't=' + +new Date)
].join('/');
if (this.isXDomain() && !io.util.ua.hasCORS) {
var insertAt = document.getElementsByTagName('script')[0]
, script = document.createElement('script');
script.src = url + '&jsonp=' + io.j.length;
insertAt.parentNode.insertBefore(script, insertAt);
io.j.push(function (data) {
complete(data);
script.parentNode.removeChild(script);
});
} else {
var xhr = io.util.request();
xhr.open('GET', url, true);
if (this.isXDomain()) {
xhr.withCredentials = true;
}
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
xhr.onreadystatechange = empty;
if (xhr.status == 200) {
complete(xhr.responseText);
} else if (xhr.status == 403) {
self.onError(xhr.responseText);
} else {
self.connecting = false;
!self.reconnecting && self.onError(xhr.responseText);
}
}
};
xhr.send(null);
}
};
/**
* Find an available transport based on the options supplied in the constructor.
*
* @api private
*/
Socket.prototype.getTransport = function (override) {
var transports = override || this.transports, match;
for (var i = 0, transport; transport = transports[i]; i++) {
if (io.Transport[transport]
&& io.Transport[transport].check(this)
&& (!this.isXDomain() || io.Transport[transport].xdomainCheck(this))) {
return new io.Transport[transport](this, this.sessionid);
}
}
return null;
};
/**
* Connects to the server.
*
* @param {Function} [fn] Callback.
* @returns {io.Socket}
* @api public
*/
Socket.prototype.connect = function (fn) {
if (this.connecting) {
return this;
}
var self = this;
self.connecting = true;
this.handshake(function (sid, heartbeat, close, transports) {
self.sessionid = sid;
self.closeTimeout = close * 1000;
self.heartbeatTimeout = heartbeat * 1000;
if(!self.transports)
self.transports = self.origTransports = (transports ? io.util.intersect(
transports.split(',')
, self.options.transports
) : self.options.transports);
self.setHeartbeatTimeout();
function connect (transports){
if (self.transport) self.transport.clearTimeouts();
self.transport = self.getTransport(transports);
if (!self.transport) return self.publish('connect_failed');
// once the transport is ready
self.transport.ready(self, function () {
self.connecting = true;
self.publish('connecting', self.transport.name);
self.transport.open();
if (self.options['connect timeout']) {
self.connectTimeoutTimer = setTimeout(function () {
if (!self.connected) {
self.connecting = false;
if (self.options['try multiple transports']) {
var remaining = self.transports;
while (remaining.length > 0 && remaining.splice(0,1)[0] !=
self.transport.name) {}
if (remaining.length){
connect(remaining);
} else {
self.publish('connect_failed');
}
}
}
}, self.options['connect timeout']);
}
});
}
connect(self.transports);
self.once('connect', function (){
clearTimeout(self.connectTimeoutTimer);
fn && typeof fn == 'function' && fn();
});
});
return this;
};
/**
* Clears and sets a new heartbeat timeout using the value given by the
* server during the handshake.
*
* @api private
*/
Socket.prototype.setHeartbeatTimeout = function () {
clearTimeout(this.heartbeatTimeoutTimer);
if(this.transport && !this.transport.heartbeats()) return;
var self = this;
this.heartbeatTimeoutTimer = setTimeout(function () {
self.transport.onClose();
}, this.heartbeatTimeout);
};
/**
* Sends a message.
*
* @param {Object} data packet.
* @returns {io.Socket}
* @api public
*/
Socket.prototype.packet = function (data) {
if (this.connected && !this.doBuffer) {
this.transport.packet(data);
} else {
this.buffer.push(data);
}
return this;
};
/**
* Sets buffer state
*
* @api private
*/
Socket.prototype.setBuffer = function (v) {
this.doBuffer = v;
if (!v && this.connected && this.buffer.length) {
if (!this.options['manualFlush']) {
this.flushBuffer();
}
}
};
/**
* Flushes the buffer data over the wire.
* To be invoked manually when 'manualFlush' is set to true.
*
* @api public
*/
Socket.prototype.flushBuffer = function() {
this.transport.payload(this.buffer);
this.buffer = [];
};
/**
* Disconnect the established connect.
*
* @returns {io.Socket}
* @api public
*/
Socket.prototype.disconnect = function () {
if (this.connected || this.connecting) {
if (this.open) {
this.of('').packet({ type: 'disconnect' });
}
// handle disconnection immediately
this.onDisconnect('booted');
}
return this;
};
/**
* Disconnects the socket with a sync XHR.
*
* @api private
*/
Socket.prototype.disconnectSync = function () {
// ensure disconnection
var xhr = io.util.request();
var uri = [
'http' + (this.options.secure ? 's' : '') + ':/'
, this.options.host + ':' + this.options.port
, this.options.resource
, io.protocol
, ''
, this.sessionid
].join('/') + '/?disconnect=1';
xhr.open('GET', uri, false);
xhr.send(null);
// handle disconnection immediately
this.onDisconnect('booted');
};
/**
* Check if we need to use cross domain enabled transports. Cross domain would
* be a different port or different domain name.
*
* @returns {Boolean}
* @api private
*/
Socket.prototype.isXDomain = function () {
// if node
return false;
// end node
var port = global.location.port ||
('https:' == global.location.protocol ? 443 : 80);
return this.options.host !== global.location.hostname
|| this.options.port != port;
};
/**
* Called upon handshake.
*
* @api private
*/
Socket.prototype.onConnect = function () {
if (!this.connected) {
this.connected = true;
this.connecting = false;
if (!this.doBuffer) {
// make sure to flush the buffer
this.setBuffer(false);
}
this.emit('connect');
}
};
/**
* Called when the transport opens
*
* @api private
*/
Socket.prototype.onOpen = function () {
this.open = true;
};
/**
* Called when the transport closes.
*
* @api private
*/
Socket.prototype.onClose = function () {
this.open = false;
clearTimeout(this.heartbeatTimeoutTimer);
};
/**
* Called when the transport first opens a connection
*
* @param text
*/
Socket.prototype.onPacket = function (packet) {
this.of(packet.endpoint).onPacket(packet);
};
/**
* Handles an error.
*
* @api private
*/
Socket.prototype.onError = function (err) {
if (err && err.advice) {
if (err.advice === 'reconnect' && (this.connected || this.connecting)) {
this.disconnect();
if (this.options.reconnect) {
this.reconnect();
}
}
}
this.publish('error', err && err.reason ? err.reason : err);
};
/**
* Called when the transport disconnects.
*
* @api private
*/
Socket.prototype.onDisconnect = function (reason) {
var wasConnected = this.connected
, wasConnecting = this.connecting;
this.connected = false;
this.connecting = false;
this.open = false;
if (wasConnected || wasConnecting) {
this.transport.close();
this.transport.clearTimeouts();
if (wasConnected) {
this.publish('disconnect', reason);
if ('booted' != reason && this.options.reconnect && !this.reconnecting) {
this.reconnect();
}
}
}
};
/**
* Called upon reconnection.
*
* @api private
*/
Socket.prototype.reconnect = function () {
this.reconnecting = true;
this.reconnectionAttempts = 0;
this.reconnectionDelay = this.options['reconnection delay'];
var self = this
, maxAttempts = this.options['max reconnection attempts']
, tryMultiple = this.options['try multiple transports']
, limit = this.options['reconnection limit'];
function reset () {
if (self.connected) {
for (var i in self.namespaces) {
if (self.namespaces.hasOwnProperty(i) && '' !== i) {
self.namespaces[i].packet({ type: 'connect' });
}
}
self.publish('reconnect', self.transport.name, self.reconnectionAttempts);
}
clearTimeout(self.reconnectionTimer);
self.removeListener('connect_failed', maybeReconnect);
self.removeListener('connect', maybeReconnect);
self.reconnecting = false;
delete self.reconnectionAttempts;
delete self.reconnectionDelay;
delete self.reconnectionTimer;
delete self.redoTransports;
self.options['try multiple transports'] = tryMultiple;
};
function maybeReconnect () {
if (!self.reconnecting) {
return;
}
if (self.connected) {
return reset();
};
if (self.connecting && self.reconnecting) {
return self.reconnectionTimer = setTimeout(maybeReconnect, 1000);
}
if (self.reconnectionAttempts++ >= maxAttempts) {
if (!self.redoTransports) {
self.on('connect_failed', maybeReconnect);
self.options['try multiple transports'] = true;
self.transports = self.origTransports;
self.transport = self.getTransport();
self.redoTransports = true;
self.connect();
} else {
self.publish('reconnect_failed');
reset();
}
} else {
if (self.reconnectionDelay < limit) {
self.reconnectionDelay *= 2; // exponential back off
}
self.connect();
self.publish('reconnecting', self.reconnectionDelay, self.reconnectionAttempts);
self.reconnectionTimer = setTimeout(maybeReconnect, self.reconnectionDelay);
}
};
this.options['try multiple transports'] = false;
this.reconnectionTimer = setTimeout(maybeReconnect, this.reconnectionDelay);
this.on('connect', maybeReconnect);
};
})(
'undefined' != typeof io ? io : module.exports
, 'undefined' != typeof io ? io : module.parent.exports
, this
);

View file

@ -1,256 +0,0 @@
/**
* socket.io
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
(function (exports, io) {
/**
* Expose constructor.
*/
exports.Transport = Transport;
/**
* This is the transport template for all supported transport methods.
*
* @constructor
* @api public
*/
function Transport (socket, sessid) {
this.socket = socket;
this.sessid = sessid;
};
/**
* Apply EventEmitter mixin.
*/
io.util.mixin(Transport, io.EventEmitter);
/**
* Indicates whether heartbeats is enabled for this transport
*
* @api private
*/
Transport.prototype.heartbeats = function () {
return true;
};
/**
* Handles the response from the server. When a new response is received
* it will automatically update the timeout, decode the message and
* forwards the response to the onMessage function for further processing.
*
* @param {String} data Response from the server.
* @api private
*/
Transport.prototype.onData = function (data) {
this.clearCloseTimeout();
// If the connection in currently open (or in a reopening state) reset the close
// timeout since we have just received data. This check is necessary so
// that we don't reset the timeout on an explicitly disconnected connection.
if (this.socket.connected || this.socket.connecting || this.socket.reconnecting) {
this.setCloseTimeout();
}
if (data !== '') {
// todo: we should only do decodePayload for xhr transports
var msgs = io.parser.decodePayload(data);
if (msgs && msgs.length) {
for (var i = 0, l = msgs.length; i < l; i++) {
this.onPacket(msgs[i]);
}
}
}
return this;
};
/**
* Handles packets.
*
* @api private
*/
Transport.prototype.onPacket = function (packet) {
this.socket.setHeartbeatTimeout();
if (packet.type == 'heartbeat') {
return this.onHeartbeat();
}
if (packet.type == 'connect' && packet.endpoint == '') {
this.onConnect();
}
if (packet.type == 'error' && packet.advice == 'reconnect') {
this.isOpen = false;
}
this.socket.onPacket(packet);
return this;
};
/**
* Sets close timeout
*
* @api private
*/
Transport.prototype.setCloseTimeout = function () {
if (!this.closeTimeout) {
var self = this;
this.closeTimeout = setTimeout(function () {
self.onDisconnect();
}, this.socket.closeTimeout);
}
};
/**
* Called when transport disconnects.
*
* @api private
*/
Transport.prototype.onDisconnect = function () {
if (this.isOpen) this.close();
this.clearTimeouts();
this.socket.onDisconnect();
return this;
};
/**
* Called when transport connects
*
* @api private
*/
Transport.prototype.onConnect = function () {
this.socket.onConnect();
return this;
};
/**
* Clears close timeout
*
* @api private
*/
Transport.prototype.clearCloseTimeout = function () {
if (this.closeTimeout) {
clearTimeout(this.closeTimeout);
this.closeTimeout = null;
}
};
/**
* Clear timeouts
*
* @api private
*/
Transport.prototype.clearTimeouts = function () {
this.clearCloseTimeout();
if (this.reopenTimeout) {
clearTimeout(this.reopenTimeout);
}
};
/**
* Sends a packet
*
* @param {Object} packet object.
* @api private
*/
Transport.prototype.packet = function (packet) {
this.send(io.parser.encodePacket(packet));
};
/**
* Send the received heartbeat message back to server. So the server
* knows we are still connected.
*
* @param {String} heartbeat Heartbeat response from the server.
* @api private
*/
Transport.prototype.onHeartbeat = function (heartbeat) {
this.packet({ type: 'heartbeat' });
};
/**
* Called when the transport opens.
*
* @api private
*/
Transport.prototype.onOpen = function () {
this.isOpen = true;
this.clearCloseTimeout();
this.socket.onOpen();
};
/**
* Notifies the base when the connection with the Socket.IO server
* has been disconnected.
*
* @api private
*/
Transport.prototype.onClose = function () {
var self = this;
/* FIXME: reopen delay causing a infinit loop
this.reopenTimeout = setTimeout(function () {
self.open();
}, this.socket.options['reopen delay']);*/
this.isOpen = false;
this.socket.onClose();
this.onDisconnect();
};
/**
* Generates a connection url based on the Socket.IO URL Protocol.
* See <https://github.com/learnboost/socket.io-node/> for more details.
*
* @returns {String} Connection url
* @api private
*/
Transport.prototype.prepareUrl = function () {
var options = this.socket.options;
return this.scheme() + '://'
+ options.host + ':' + options.port + '/'
+ options.resource + '/' + io.protocol
+ '/' + this.name + '/' + this.sessid;
};
/**
* Checks if the transport is ready to start a connection.
*
* @param {Socket} socket The socket instance that needs a transport
* @param {Function} fn The callback
* @api private
*/
Transport.prototype.ready = function (socket, fn) {
fn.call(this);
};
})(
'undefined' != typeof io ? io : module.exports
, 'undefined' != typeof io ? io : module.parent.exports
);

View file

@ -1,191 +0,0 @@
/**
* socket.io
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
(function (exports, io) {
/**
* Expose constructor.
*/
exports.flashsocket = Flashsocket;
/**
* The FlashSocket transport. This is a API wrapper for the HTML5 WebSocket
* specification. It uses a .swf file to communicate with the server. If you want
* to serve the .swf file from a other server than where the Socket.IO script is
* coming from you need to use the insecure version of the .swf. More information
* about this can be found on the github page.
*
* @constructor
* @extends {io.Transport.websocket}
* @api public
*/
function Flashsocket () {
io.Transport.websocket.apply(this, arguments);
};
/**
* Inherits from Transport.
*/
io.util.inherit(Flashsocket, io.Transport.websocket);
/**
* Transport name
*
* @api public
*/
Flashsocket.prototype.name = 'flashsocket';
/**
* Disconnect the established `FlashSocket` connection. This is done by adding a
* new task to the FlashSocket. The rest will be handled off by the `WebSocket`
* transport.
*
* @returns {Transport}
* @api public
*/
Flashsocket.prototype.open = function () {
var self = this
, args = arguments;
WebSocket.__addTask(function () {
io.Transport.websocket.prototype.open.apply(self, args);
});
return this;
};
/**
* Sends a message to the Socket.IO server. This is done by adding a new
* task to the FlashSocket. The rest will be handled off by the `WebSocket`
* transport.
*
* @returns {Transport}
* @api public
*/
Flashsocket.prototype.send = function () {
var self = this, args = arguments;
WebSocket.__addTask(function () {
io.Transport.websocket.prototype.send.apply(self, args);
});
return this;
};
/**
* Disconnects the established `FlashSocket` connection.
*
* @returns {Transport}
* @api public
*/
Flashsocket.prototype.close = function () {
WebSocket.__tasks.length = 0;
io.Transport.websocket.prototype.close.call(this);
return this;
};
/**
* The WebSocket fall back needs to append the flash container to the body
* element, so we need to make sure we have access to it. Or defer the call
* until we are sure there is a body element.
*
* @param {Socket} socket The socket instance that needs a transport
* @param {Function} fn The callback
* @api private
*/
Flashsocket.prototype.ready = function (socket, fn) {
function init () {
var options = socket.options
, port = options['flash policy port']
, path = [
'http' + (options.secure ? 's' : '') + ':/'
, options.host + ':' + options.port
, options.resource
, 'static/flashsocket'
, 'WebSocketMain' + (socket.isXDomain() ? 'Insecure' : '') + '.swf'
];
// Only start downloading the swf file when the checked that this browser
// actually supports it
if (!Flashsocket.loaded) {
if (typeof WEB_SOCKET_SWF_LOCATION === 'undefined') {
// Set the correct file based on the XDomain settings
WEB_SOCKET_SWF_LOCATION = path.join('/');
}
if (port !== 843) {
WebSocket.loadFlashPolicyFile('xmlsocket://' + options.host + ':' + port);
}
WebSocket.__initialize();
Flashsocket.loaded = true;
}
fn.call(self);
}
var self = this;
if (document.body) return init();
io.util.load(init);
};
/**
* Check if the FlashSocket transport is supported as it requires that the Adobe
* Flash Player plug-in version `10.0.0` or greater is installed. And also check if
* the polyfill is correctly loaded.
*
* @returns {Boolean}
* @api public
*/
Flashsocket.check = function () {
if (
typeof WebSocket == 'undefined'
|| !('__initialize' in WebSocket) || !swfobject
) return false;
return swfobject.getFlashPlayerVersion().major >= 10;
};
/**
* Check if the FlashSocket transport can be used as cross domain / cross origin
* transport. Because we can't see which type (secure or insecure) of .swf is used
* we will just return true.
*
* @returns {Boolean}
* @api public
*/
Flashsocket.xdomainCheck = function () {
return true;
};
/**
* Disable AUTO_INITIALIZATION
*/
if (typeof window != 'undefined') {
WEB_SOCKET_DISABLE_AUTO_INITIALIZATION = true;
}
/**
* Add the transport to your public io.transports array.
*
* @api private
*/
io.transports.push('flashsocket');
})(
'undefined' != typeof io ? io.Transport : module.exports
, 'undefined' != typeof io ? io : module.parent.exports
);

View file

@ -1,171 +0,0 @@
/**
* socket.io
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
(function (exports, io) {
/**
* Expose constructor.
*/
exports.htmlfile = HTMLFile;
/**
* The HTMLFile transport creates a `forever iframe` based transport
* for Internet Explorer. Regular forever iframe implementations will
* continuously trigger the browsers buzy indicators. If the forever iframe
* is created inside a `htmlfile` these indicators will not be trigged.
*
* @constructor
* @extends {io.Transport.XHR}
* @api public
*/
function HTMLFile (socket) {
io.Transport.XHR.apply(this, arguments);
};
/**
* Inherits from XHR transport.
*/
io.util.inherit(HTMLFile, io.Transport.XHR);
/**
* Transport name
*
* @api public
*/
HTMLFile.prototype.name = 'htmlfile';
/**
* Creates a new ActiveX `htmlfile` with a forever loading iframe
* that can be used to listen to messages. Inside the generated
* `htmlfile` a reference will be made to the HTMLFile transport.
*
* @api private
*/
HTMLFile.prototype.get = function () {
this.doc = new ActiveXObject('htmlfile');
this.doc.open();
this.doc.write('<html></html>');
this.doc.close();
this.doc.parentWindow.s = this;
var iframeC = this.doc.createElement('div');
iframeC.className = 'socketio';
this.doc.body.appendChild(iframeC);
this.iframe = this.doc.createElement('iframe');
iframeC.appendChild(this.iframe);
var self = this
, query = io.util.query(this.socket.options.query, 't='+ +new Date);
this.iframe.src = this.prepareUrl() + query;
io.util.on(window, 'unload', function () {
self.destroy();
});
};
/**
* The Socket.IO server will write script tags inside the forever
* iframe, this function will be used as callback for the incoming
* information.
*
* @param {String} data The message
* @param {document} doc Reference to the context
* @api private
*/
HTMLFile.prototype._ = function (data, doc) {
this.onData(data);
try {
var script = doc.getElementsByTagName('script')[0];
script.parentNode.removeChild(script);
} catch (e) { }
};
/**
* Destroy the established connection, iframe and `htmlfile`.
* And calls the `CollectGarbage` function of Internet Explorer
* to release the memory.
*
* @api private
*/
HTMLFile.prototype.destroy = function () {
if (this.iframe){
try {
this.iframe.src = 'about:blank';
} catch(e){}
this.doc = null;
this.iframe.parentNode.removeChild(this.iframe);
this.iframe = null;
CollectGarbage();
}
};
/**
* Disconnects the established connection.
*
* @returns {Transport} Chaining.
* @api public
*/
HTMLFile.prototype.close = function () {
this.destroy();
return io.Transport.XHR.prototype.close.call(this);
};
/**
* Checks if the browser supports this transport. The browser
* must have an `ActiveXObject` implementation.
*
* @return {Boolean}
* @api public
*/
HTMLFile.check = function (socket) {
if (typeof window != "undefined" && 'ActiveXObject' in window){
try {
var a = new ActiveXObject('htmlfile');
return a && io.Transport.XHR.check(socket);
} catch(e){}
}
return false;
};
/**
* Check if cross domain requests are supported.
*
* @returns {Boolean}
* @api public
*/
HTMLFile.xdomainCheck = function () {
// we can probably do handling for sub-domains, we should
// test that it's cross domain but a subdomain here
return false;
};
/**
* Add the transport to your public io.transports array.
*
* @api private
*/
io.transports.push('htmlfile');
})(
'undefined' != typeof io ? io.Transport : module.exports
, 'undefined' != typeof io ? io : module.parent.exports
);

View file

@ -1,256 +0,0 @@
/**
* socket.io
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
(function (exports, io, global) {
/**
* There is a way to hide the loading indicator in Firefox. If you create and
* remove a iframe it will stop showing the current loading indicator.
* Unfortunately we can't feature detect that and UA sniffing is evil.
*
* @api private
*/
var indicator = global.document && "MozAppearance" in
global.document.documentElement.style;
/**
* Expose constructor.
*/
exports['jsonp-polling'] = JSONPPolling;
/**
* The JSONP transport creates an persistent connection by dynamically
* inserting a script tag in the page. This script tag will receive the
* information of the Socket.IO server. When new information is received
* it creates a new script tag for the new data stream.
*
* @constructor
* @extends {io.Transport.xhr-polling}
* @api public
*/
function JSONPPolling (socket) {
io.Transport['xhr-polling'].apply(this, arguments);
this.index = io.j.length;
var self = this;
io.j.push(function (msg) {
self._(msg);
});
};
/**
* Inherits from XHR polling transport.
*/
io.util.inherit(JSONPPolling, io.Transport['xhr-polling']);
/**
* Transport name
*
* @api public
*/
JSONPPolling.prototype.name = 'jsonp-polling';
/**
* Posts a encoded message to the Socket.IO server using an iframe.
* The iframe is used because script tags can create POST based requests.
* The iframe is positioned outside of the view so the user does not
* notice it's existence.
*
* @param {String} data A encoded message.
* @api private
*/
JSONPPolling.prototype.post = function (data) {
var self = this
, query = io.util.query(
this.socket.options.query
, 't='+ (+new Date) + '&i=' + this.index
);
if (!this.form) {
var form = document.createElement('form')
, area = document.createElement('textarea')
, id = this.iframeId = 'socketio_iframe_' + this.index
, iframe;
form.className = 'socketio';
form.style.position = 'absolute';
form.style.top = '0px';
form.style.left = '0px';
form.style.display = 'none';
form.target = id;
form.method = 'POST';
form.setAttribute('accept-charset', 'utf-8');
area.name = 'd';
form.appendChild(area);
document.body.appendChild(form);
this.form = form;
this.area = area;
}
this.form.action = this.prepareUrl() + query;
function complete () {
initIframe();
self.socket.setBuffer(false);
};
function initIframe () {
if (self.iframe) {
self.form.removeChild(self.iframe);
}
try {
// ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
iframe = document.createElement('<iframe name="'+ self.iframeId +'">');
} catch (e) {
iframe = document.createElement('iframe');
iframe.name = self.iframeId;
}
iframe.id = self.iframeId;
self.form.appendChild(iframe);
self.iframe = iframe;
};
initIframe();
// we temporarily stringify until we figure out how to prevent
// browsers from turning `\n` into `\r\n` in form inputs
this.area.value = io.JSON.stringify(data);
try {
this.form.submit();
} catch(e) {}
if (this.iframe.attachEvent) {
iframe.onreadystatechange = function () {
if (self.iframe.readyState == 'complete') {
complete();
}
};
} else {
this.iframe.onload = complete;
}
this.socket.setBuffer(true);
};
/**
* Creates a new JSONP poll that can be used to listen
* for messages from the Socket.IO server.
*
* @api private
*/
JSONPPolling.prototype.get = function () {
var self = this
, script = document.createElement('script')
, query = io.util.query(
this.socket.options.query
, 't='+ (+new Date) + '&i=' + this.index
);
if (this.script) {
this.script.parentNode.removeChild(this.script);
this.script = null;
}
script.async = true;
script.src = this.prepareUrl() + query;
script.onerror = function () {
self.onClose();
};
var insertAt = document.getElementsByTagName('script')[0];
insertAt.parentNode.insertBefore(script, insertAt);
this.script = script;
if (indicator) {
setTimeout(function () {
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
document.body.removeChild(iframe);
}, 100);
}
};
/**
* Callback function for the incoming message stream from the Socket.IO server.
*
* @param {String} data The message
* @api private
*/
JSONPPolling.prototype._ = function (msg) {
this.onData(msg);
if (this.isOpen) {
this.get();
}
return this;
};
/**
* The indicator hack only works after onload
*
* @param {Socket} socket The socket instance that needs a transport
* @param {Function} fn The callback
* @api private
*/
JSONPPolling.prototype.ready = function (socket, fn) {
var self = this;
if (!indicator) return fn.call(this);
io.util.load(function () {
fn.call(self);
});
};
/**
* Checks if browser supports this transport.
*
* @return {Boolean}
* @api public
*/
JSONPPolling.check = function () {
return 'document' in global;
};
/**
* Check if cross domain requests are supported
*
* @returns {Boolean}
* @api public
*/
JSONPPolling.xdomainCheck = function () {
return true;
};
/**
* Add the transport to your public io.transports array.
*
* @api private
*/
io.transports.push('jsonp-polling');
})(
'undefined' != typeof io ? io.Transport : module.exports
, 'undefined' != typeof io ? io : module.parent.exports
, this
);

View file

@ -1,197 +0,0 @@
/**
* socket.io
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
(function (exports, io, global) {
/**
* Expose constructor.
*/
exports.websocket = WS;
/**
* The WebSocket transport uses the HTML5 WebSocket API to establish an
* persistent connection with the Socket.IO server. This transport will also
* be inherited by the FlashSocket fallback as it provides a API compatible
* polyfill for the WebSockets.
*
* @constructor
* @extends {io.Transport}
* @api public
*/
function WS (socket) {
io.Transport.apply(this, arguments);
};
/**
* Inherits from Transport.
*/
io.util.inherit(WS, io.Transport);
/**
* Transport name
*
* @api public
*/
WS.prototype.name = 'websocket';
/**
* Initializes a new `WebSocket` connection with the Socket.IO server. We attach
* all the appropriate listeners to handle the responses from the server.
*
* @returns {Transport}
* @api public
*/
WS.prototype.open = function () {
var query = io.util.query(this.socket.options.query)
, self = this
, Socket
// if node
Socket = require('ws');
// end node
if (!Socket) {
Socket = global.MozWebSocket || global.WebSocket;
}
this.websocket = new Socket(this.prepareUrl() + query);
this.websocket.onopen = function () {
self.onOpen();
self.socket.setBuffer(false);
};
this.websocket.onmessage = function (ev) {
self.onData(ev.data);
};
this.websocket.onclose = function () {
self.onClose();
self.socket.setBuffer(true);
};
this.websocket.onerror = function (e) {
self.onError(e);
};
return this;
};
/**
* Send a message to the Socket.IO server. The message will automatically be
* encoded in the correct message format.
*
* @returns {Transport}
* @api public
*/
// Do to a bug in the current IDevices browser, we need to wrap the send in a
// setTimeout, when they resume from sleeping the browser will crash if
// we don't allow the browser time to detect the socket has been closed
if (io.util.ua.iDevice) {
WS.prototype.send = function (data) {
var self = this;
setTimeout(function() {
self.websocket.send(data);
},0);
return this;
};
} else {
WS.prototype.send = function (data) {
this.websocket.send(data);
return this;
};
}
/**
* Payload
*
* @api private
*/
WS.prototype.payload = function (arr) {
for (var i = 0, l = arr.length; i < l; i++) {
this.packet(arr[i]);
}
return this;
};
/**
* Disconnect the established `WebSocket` connection.
*
* @returns {Transport}
* @api public
*/
WS.prototype.close = function () {
this.websocket.close();
return this;
};
/**
* Handle the errors that `WebSocket` might be giving when we
* are attempting to connect or send messages.
*
* @param {Error} e The error.
* @api private
*/
WS.prototype.onError = function (e) {
this.socket.onError(e);
};
/**
* Returns the appropriate scheme for the URI generation.
*
* @api private
*/
WS.prototype.scheme = function () {
return this.socket.options.secure ? 'wss' : 'ws';
};
/**
* Checks if the browser has support for native `WebSockets` and that
* it's not the polyfill created for the FlashSocket transport.
*
* @return {Boolean}
* @api public
*/
WS.check = function () {
// if node
return true;
// end node
return ('WebSocket' in global && !('__addTask' in WebSocket))
|| 'MozWebSocket' in global;
};
/**
* Check if the `WebSocket` transport support cross domain communications.
*
* @returns {Boolean}
* @api public
*/
WS.xdomainCheck = function () {
return true;
};
/**
* Add the transport to your public io.transports array.
*
* @api private
*/
io.transports.push('websocket');
})(
'undefined' != typeof io ? io.Transport : module.exports
, 'undefined' != typeof io ? io : module.parent.exports
, this
);

View file

@ -1,177 +0,0 @@
/**
* socket.io
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
(function (exports, io, global) {
/**
* Expose constructor.
*/
exports['xhr-polling'] = XHRPolling;
/**
* The XHR-polling transport uses long polling XHR requests to create a
* "persistent" connection with the server.
*
* @constructor
* @api public
*/
function XHRPolling () {
io.Transport.XHR.apply(this, arguments);
};
/**
* Inherits from XHR transport.
*/
io.util.inherit(XHRPolling, io.Transport.XHR);
/**
* Merge the properties from XHR transport
*/
io.util.merge(XHRPolling, io.Transport.XHR);
/**
* Transport name
*
* @api public
*/
XHRPolling.prototype.name = 'xhr-polling';
/**
* Indicates whether heartbeats is enabled for this transport
*
* @api private
*/
XHRPolling.prototype.heartbeats = function () {
return false;
};
/**
* Establish a connection, for iPhone and Android this will be done once the page
* is loaded.
*
* @returns {Transport} Chaining.
* @api public
*/
XHRPolling.prototype.open = function () {
var self = this;
io.Transport.XHR.prototype.open.call(self);
return false;
};
/**
* Starts a XHR request to wait for incoming messages.
*
* @api private
*/
function empty () {};
XHRPolling.prototype.get = function () {
if (!this.isOpen) return;
var self = this;
function stateChange () {
if (this.readyState == 4) {
this.onreadystatechange = empty;
if (this.status == 200) {
self.onData(this.responseText);
self.get();
} else {
self.onClose();
}
}
};
function onload () {
this.onload = empty;
this.onerror = empty;
self.retryCounter = 1;
self.onData(this.responseText);
self.get();
};
function onerror () {
self.retryCounter ++;
if(!self.retryCounter || self.retryCounter > 3) {
self.onClose();
} else {
self.get();
}
};
this.xhr = this.request();
if (global.XDomainRequest && this.xhr instanceof XDomainRequest) {
this.xhr.onload = onload;
this.xhr.onerror = onerror;
} else {
this.xhr.onreadystatechange = stateChange;
}
this.xhr.send(null);
};
/**
* Handle the unclean close behavior.
*
* @api private
*/
XHRPolling.prototype.onClose = function () {
io.Transport.XHR.prototype.onClose.call(this);
if (this.xhr) {
this.xhr.onreadystatechange = this.xhr.onload = this.xhr.onerror = empty;
try {
this.xhr.abort();
} catch(e){}
this.xhr = null;
}
};
/**
* Webkit based browsers show a infinit spinner when you start a XHR request
* before the browsers onload event is called so we need to defer opening of
* the transport until the onload event is called. Wrapping the cb in our
* defer method solve this.
*
* @param {Socket} socket The socket instance that needs a transport
* @param {Function} fn The callback
* @api private
*/
XHRPolling.prototype.ready = function (socket, fn) {
var self = this;
io.util.defer(function () {
fn.call(self);
});
};
/**
* Add the transport to your public io.transports array.
*
* @api private
*/
io.transports.push('xhr-polling');
})(
'undefined' != typeof io ? io.Transport : module.exports
, 'undefined' != typeof io ? io : module.parent.exports
, this
);

View file

@ -1,217 +0,0 @@
/**
* socket.io
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
(function (exports, io, global) {
/**
* Expose constructor.
*
* @api public
*/
exports.XHR = XHR;
/**
* XHR constructor
*
* @costructor
* @api public
*/
function XHR (socket) {
if (!socket) return;
io.Transport.apply(this, arguments);
this.sendBuffer = [];
};
/**
* Inherits from Transport.
*/
io.util.inherit(XHR, io.Transport);
/**
* Establish a connection
*
* @returns {Transport}
* @api public
*/
XHR.prototype.open = function () {
this.socket.setBuffer(false);
this.onOpen();
this.get();
// we need to make sure the request succeeds since we have no indication
// whether the request opened or not until it succeeded.
this.setCloseTimeout();
return this;
};
/**
* Check if we need to send data to the Socket.IO server, if we have data in our
* buffer we encode it and forward it to the `post` method.
*
* @api private
*/
XHR.prototype.payload = function (payload) {
var msgs = [];
for (var i = 0, l = payload.length; i < l; i++) {
msgs.push(io.parser.encodePacket(payload[i]));
}
this.send(io.parser.encodePayload(msgs));
};
/**
* Send data to the Socket.IO server.
*
* @param data The message
* @returns {Transport}
* @api public
*/
XHR.prototype.send = function (data) {
this.post(data);
return this;
};
/**
* Posts a encoded message to the Socket.IO server.
*
* @param {String} data A encoded message.
* @api private
*/
function empty () { };
XHR.prototype.post = function (data) {
var self = this;
this.socket.setBuffer(true);
function stateChange () {
if (this.readyState == 4) {
this.onreadystatechange = empty;
self.posting = false;
if (this.status == 200){
self.socket.setBuffer(false);
} else {
self.onClose();
}
}
}
function onload () {
this.onload = empty;
self.socket.setBuffer(false);
};
this.sendXHR = this.request('POST');
if (global.XDomainRequest && this.sendXHR instanceof XDomainRequest) {
this.sendXHR.onload = this.sendXHR.onerror = onload;
} else {
this.sendXHR.onreadystatechange = stateChange;
}
this.sendXHR.send(data);
};
/**
* Disconnects the established `XHR` connection.
*
* @returns {Transport}
* @api public
*/
XHR.prototype.close = function () {
this.onClose();
return this;
};
/**
* Generates a configured XHR request
*
* @param {String} url The url that needs to be requested.
* @param {String} method The method the request should use.
* @returns {XMLHttpRequest}
* @api private
*/
XHR.prototype.request = function (method) {
var req = io.util.request(this.socket.isXDomain())
, query = io.util.query(this.socket.options.query, 't=' + +new Date);
req.open(method || 'GET', this.prepareUrl() + query, true);
if (method == 'POST') {
try {
if (req.setRequestHeader) {
req.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
} else {
// XDomainRequest
req.contentType = 'text/plain';
}
} catch (e) {}
}
return req;
};
/**
* Returns the scheme to use for the transport URLs.
*
* @api private
*/
XHR.prototype.scheme = function () {
return this.socket.options.secure ? 'https' : 'http';
};
/**
* Check if the XHR transports are supported
*
* @param {Boolean} xdomain Check if we support cross domain requests.
* @returns {Boolean}
* @api public
*/
XHR.check = function (socket, xdomain) {
try {
var request = io.util.request(xdomain),
usesXDomReq = (global.XDomainRequest && request instanceof XDomainRequest),
socketProtocol = (socket && socket.options && socket.options.secure ? 'https:' : 'http:'),
isXProtocol = (global.location && socketProtocol != global.location.protocol);
if (request && !(usesXDomReq && isXProtocol)) {
return true;
}
} catch(e) {}
return false;
};
/**
* Check if the XHR transport supports cross domain requests.
*
* @returns {Boolean}
* @api public
*/
XHR.xdomainCheck = function (socket) {
return XHR.check(socket, true);
};
})(
'undefined' != typeof io ? io.Transport : module.exports
, 'undefined' != typeof io ? io : module.parent.exports
, this
);

View file

@ -1,365 +0,0 @@
/**
* socket.io
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
* MIT Licensed
*/
(function (exports, global) {
/**
* Utilities namespace.
*
* @namespace
*/
var util = exports.util = {};
/**
* Parses an URI
*
* @author Steven Levithan <stevenlevithan.com> (MIT license)
* @api public
*/
var re = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
var parts = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password',
'host', 'port', 'relative', 'path', 'directory', 'file', 'query',
'anchor'];
util.parseUri = function (str) {
var m = re.exec(str || '')
, uri = {}
, i = 14;
while (i--) {
uri[parts[i]] = m[i] || '';
}
return uri;
};
/**
* Produces a unique url that identifies a Socket.IO connection.
*
* @param {Object} uri
* @api public
*/
util.uniqueUri = function (uri) {
var protocol = uri.protocol
, host = uri.host
, port = uri.port;
if ('document' in global) {
host = host || document.domain;
port = port || (protocol == 'https'
&& document.location.protocol !== 'https:' ? 443 : document.location.port);
} else {
host = host || 'localhost';
if (!port && protocol == 'https') {
port = 443;
}
}
return (protocol || 'http') + '://' + host + ':' + (port || 80);
};
/**
* Mergest 2 query strings in to once unique query string
*
* @param {String} base
* @param {String} addition
* @api public
*/
util.query = function (base, addition) {
var query = util.chunkQuery(base || '')
, components = [];
util.merge(query, util.chunkQuery(addition || ''));
for (var part in query) {
if (query.hasOwnProperty(part)) {
components.push(part + '=' + query[part]);
}
}
return components.length ? '?' + components.join('&') : '';
};
/**
* Transforms a querystring in to an object
*
* @param {String} qs
* @api public
*/
util.chunkQuery = function (qs) {
var query = {}
, params = qs.split('&')
, i = 0
, l = params.length
, kv;
for (; i < l; ++i) {
kv = params[i].split('=');
if (kv[0]) {
query[kv[0]] = kv[1];
}
}
return query;
};
/**
* Executes the given function when the page is loaded.
*
* io.util.load(function () { console.log('page loaded'); });
*
* @param {Function} fn
* @api public
*/
var pageLoaded = false;
util.load = function (fn) {
if ('document' in global && document.readyState === 'complete' || pageLoaded) {
return fn();
}
util.on(global, 'load', fn, false);
};
/**
* Adds an event.
*
* @api private
*/
util.on = function (element, event, fn, capture) {
if (element.attachEvent) {
element.attachEvent('on' + event, fn);
} else if (element.addEventListener) {
element.addEventListener(event, fn, capture);
}
};
/**
* Generates the correct `XMLHttpRequest` for regular and cross domain requests.
*
* @param {Boolean} [xdomain] Create a request that can be used cross domain.
* @returns {XMLHttpRequest|false} If we can create a XMLHttpRequest.
* @api private
*/
util.request = function (xdomain) {
// if node
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;
return new XMLHttpRequest();
// end node
if (xdomain && 'undefined' != typeof XDomainRequest && !util.ua.hasCORS) {
return new XDomainRequest();
}
if ('undefined' != typeof XMLHttpRequest && (!xdomain || util.ua.hasCORS)) {
return new XMLHttpRequest();
}
if (!xdomain) {
try {
return new ActiveXObject('Microsoft.XMLHTTP');
} catch(e) { }
}
return null;
};
/**
* XHR based transport constructor.
*
* @constructor
* @api public
*/
/**
* Change the internal pageLoaded value.
*/
if ('undefined' != typeof window) {
util.load(function () {
pageLoaded = true;
});
}
/**
* Defers a function to ensure a spinner is not displayed by the browser
*
* @param {Function} fn
* @api public
*/
util.defer = function (fn) {
if (!util.ua.webkit || 'undefined' != typeof importScripts) {
return fn();
}
util.load(function () {
setTimeout(fn, 100);
});
};
/**
* Merges two objects.
*
* @api public
*/
util.merge = function merge (target, additional, deep, lastseen) {
var seen = lastseen || []
, depth = typeof deep == 'undefined' ? 2 : deep
, prop;
for (prop in additional) {
if (additional.hasOwnProperty(prop) && util.indexOf(seen, prop) < 0) {
if (typeof target[prop] !== 'object' || !depth) {
target[prop] = additional[prop];
seen.push(additional[prop]);
} else {
util.merge(target[prop], additional[prop], depth - 1, seen);
}
}
}
return target;
};
/**
* Merges prototypes from objects
*
* @api public
*/
util.mixin = function (ctor, ctor2) {
util.merge(ctor.prototype, ctor2.prototype);
};
/**
* Shortcut for prototypical and static inheritance.
*
* @api private
*/
util.inherit = function (ctor, ctor2) {
function f() {};
f.prototype = ctor2.prototype;
ctor.prototype = new f;
};
/**
* Checks if the given object is an Array.
*
* io.util.isArray([]); // true
* io.util.isArray({}); // false
*
* @param Object obj
* @api public
*/
util.isArray = Array.isArray || function (obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
};
/**
* Intersects values of two arrays into a third
*
* @api public
*/
util.intersect = function (arr, arr2) {
var ret = []
, longest = arr.length > arr2.length ? arr : arr2
, shortest = arr.length > arr2.length ? arr2 : arr;
for (var i = 0, l = shortest.length; i < l; i++) {
if (~util.indexOf(longest, shortest[i]))
ret.push(shortest[i]);
}
return ret;
};
/**
* Array indexOf compatibility.
*
* @see bit.ly/a5Dxa2
* @api public
*/
util.indexOf = function (arr, o, i) {
for (var j = arr.length, i = i < 0 ? i + j < 0 ? 0 : i + j : i || 0;
i < j && arr[i] !== o; i++) {}
return j <= i ? -1 : i;
};
/**
* Converts enumerables to array.
*
* @api public
*/
util.toArray = function (enu) {
var arr = [];
for (var i = 0, l = enu.length; i < l; i++)
arr.push(enu[i]);
return arr;
};
/**
* UA / engines detection namespace.
*
* @namespace
*/
util.ua = {};
/**
* Whether the UA supports CORS for XHR.
*
* @api public
*/
util.ua.hasCORS = 'undefined' != typeof XMLHttpRequest && (function () {
try {
var a = new XMLHttpRequest();
} catch (e) {
return false;
}
return a.withCredentials != undefined;
})();
/**
* Detect webkit.
*
* @api public
*/
util.ua.webkit = 'undefined' != typeof navigator
&& /webkit/i.test(navigator.userAgent);
/**
* Detect iPad/iPhone/iPod.
*
* @api public
*/
util.ua.iDevice = 'undefined' != typeof navigator
&& /iPad|iPhone|iPod/i.test(navigator.userAgent);
})('undefined' != typeof io ? io : module.exports, this);

View file

@ -1,157 +0,0 @@
## How to try the sample
Assuming you have Web server (e.g. Apache) running at **http://example.com/** .
1. Download [web-socket-ruby](http://github.com/gimite/web-socket-ruby/tree/master).
2. Run sample Web Socket server (echo server) in example.com with: (#1)<br>
```
$ ruby web-socket-ruby/samples/echo_server.rb example.com 10081
```
3. If your server already provides socket policy file at port **843**, modify the file to allow access to port **10081**. Otherwise you can skip this step. See below for details.
4. Publish the web-socket-js directory with your Web server (e.g. put it in ~/public_html).
5. Change ws://localhost:10081 to **ws://example.com:10081** in sample.html.
6. Open sample.html in your browser.
7. After "onopen" is shown, input something, click [Send] and confirm echo back.
\#1: First argument of echo_server.rb means that it accepts Web Socket connection from HTML pages in example.com.
## How to use it in your application
- Copy swfobject.js, web_socket.js, WebSocketMain.swf to your application directory.
- Write JavaScript code:
```html
<!-- Import JavaScript Libraries. -->
<script type="text/javascript" src="swfobject.js"></script>
<script type="text/javascript" src="web_socket.js"></script>
<script type="text/javascript">
// Let the library know where WebSocketMain.swf is:
WEB_SOCKET_SWF_LOCATION = "WebSocketMain.swf";
// Write your code in the same way as for native WebSocket:
var ws = new WebSocket("ws://example.com:10081/");
ws.onopen = function() {
ws.send("Hello"); // Sends a message.
};
ws.onmessage = function(e) {
// Receives a message.
alert(e.data);
};
ws.onclose = function() {
alert("closed");
};
</script>
```
- Put Flash socket policy file to your server unless you use web-socket-ruby or em-websocket as your WebSocket server. See "Flash socket policy file" section below for details.
## Troubleshooting
If it doesn't work, try these:
1. Try Chrome and Firefox 3.x.
- It doesn't work on Chrome:<br>
It's likely an issue of your code or the server. Debug your code as usual e.g. using console.log.
- It works on Chrome but it doesn't work on Firefox:<br>
It's likely an issue of web-socket-js specific configuration (e.g. 3 and 4 below).
- It works on both Chrome and Firefox, but it doesn't work on your browser:<br>
Check "Supported environment" section below. Your browser may not be supported by web-socket-js.
2. Add this line before your code:
WEB_SOCKET_DEBUG = true;
and use Developer Tools (Chrome/Safari) or Firebug (Firefox) to see if console.log outputs any errors.
3. Make sure you do NOT open your HTML page as local file e.g. file:///.../sample.html. web-socket-js doesn't work on local file. Open it via Web server e.g. http:///.../sample.html.
4. If you are NOT using web-socket-ruby or em-websocket as your WebSocket server, you need to place Flash socket policy file on your server. See "Flash socket policy file" section below for details.
5. Check if sample.html bundled with web-socket-js works.
6. Make sure the port used for WebSocket (10081 in example above) is not blocked by your server/client's firewall.
7. Install [debugger version of Flash Player](http://www.adobe.com/support/flashplayer/downloads.html) to see Flash errors.
## Supported environments
It should work on:
- Google Chrome 4 or later (just uses native implementation)
- Firefox 3.x, 4.x, Internet Explorer 8, 9 + Flash Player 10 or later
It may or may not work on other browsers such as Safari, Opera or IE 6. Patch for these browsers are appreciated, but I will not work on fixing issues specific to these browsers by myself.
## Limitations/differences compared to native WebSocket
- You need some more lines in your JavaScript code. See "How to use it in your application" section above for details.
- It requires Flash Player 10 or later unless the browser supports native WebSocket.
- Your server must provide Flash socket policy file, unless you use web-socket-ruby or em-websocket. See "Flash socket policy file" section below for details.
- It has limited support for Cookies on WebSocket. See "Cookie support" section below for details.
- It doesn't use proxies specified in browser config. See "Proxy support" section below for details.
### Flash socket policy file
This implementation uses Flash's socket, which means that your server must provide Flash socket policy file to declare the server accepts connections from Flash.
If you use [web-socket-ruby](http://github.com/gimite/web-socket-ruby/tree/master) or [em-websocket](https://github.com/igrigorik/em-websocket), you don't need anything special, because they handle Flash socket policy file request. But if you already provide socket policy file at port **843**, you need to modify the file to allow access to Web Socket port, because it precedes what the libraries provide.
If you use other Web Socket server implementation, you need to provide socket policy file yourself. See [Setting up A Flash Socket Policy File](http://www.lightsphere.com/dev/articles/flash_socket_policy.html) for details and sample script to run socket policy file server. [node.js implementation is available here](http://github.com/LearnBoost/Socket.IO-node/blob/master/lib/socket.io/transports/flashsocket.js).
Actually, it's still better to provide socket policy file at port 843 even if you use web-socket-ruby or em-websocket. Flash always try to connect to port 843 first, so providing the file at port 843 makes startup faster.
### Cookie support
web-socket-js has limited supported for Cookies on WebSocket.
Cookie is sent if Web Socket host is exactly the same as the origin of JavaScript (The port can be different). Otherwise it is not sent, because I don't know way to send right Cookie (which is Cookie of the host of Web Socket, I heard). Also, HttpOnly Cookies are not sent.
Note that it's technically possible that client sends arbitrary string as Cookie and any other headers (by modifying this library for example) once you place Flash socket policy file in your server. So don't trust Cookie and other headers if you allow connection from untrusted origin.
### Proxy support
[The WebSocket spec](http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol) specifies instructions for User Agents to support proxied connections by implementing the HTTP CONNECT method.
The AS3 Socket class doesn't implement this mechanism, which renders it useless for the scenarios where the user trying to open a socket is behind a proxy.
The class RFC2817Socket (by Christian Cantrell) effectively lets us implement this, as long as the proxy settings are known and provided by the interface that instantiates the WebSocket. As such, if you want to support proxied conncetions, you'll have to supply this information to the WebSocket constructor when Flash is being used. One way to go about it would be to ask the user for proxy settings information if the initial connection fails.
## How to host HTML file and SWF file in different domains
By default, HTML file and SWF file must be in the same domain. You can follow steps below to allow hosting them in different domain.
**WARNING**: If you use the method below, HTML files in ANY domains can send arbitrary TCP data to your WebSocket server, regardless of configuration in Flash socket policy file. Arbitrary TCP data means that they can even fake request headers including Origin and Cookie.
1. Unzip WebSocketMainInsecure.zip to extract WebSocketMainInsecure.swf.
2. Put WebSocketMainInsecure.swf on your server, instead of WebSocketMain.swf.
3. In JavaScript, set WEB_SOCKET_SWF_LOCATION to URL of your WebSocketMainInsecure.swf.
## How to build WebSocketMain.swf
Install [Flex 4 SDK](http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+4).
$ cd flash-src
$ ./build.sh
## WebSocket protocol versions
- web-socket-js supports [Hixie 76 version](http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76) of WebSocket protocol by default i.e. in [master branch](https://github.com/gimite/web-socket-js).
- If you want to try newer [Hybi 07 version](http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-07), check out from [hybi-07 branch](https://github.com/gimite/web-socket-js/tree/hybi-07). This will become the master branch in the future, probably when Chrome switches to Hybi 07.
- Hixie 75 or before is no longer supported.
## License
New BSD License.

View file

@ -1,8 +0,0 @@
package {
public interface IWebSocketLogger {
function log(message:String):void;
function error(message:String):void;
}
}

View file

@ -1,464 +0,0 @@
// Copyright: Hiroshi Ichikawa <http://gimite.net/en/>
// License: New BSD License
// Reference: http://dev.w3.org/html5/websockets/
// Reference: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76
package {
import com.adobe.net.proxies.RFC2817Socket;
import com.gsolo.encryption.MD5;
import com.hurlant.crypto.tls.TLSConfig;
import com.hurlant.crypto.tls.TLSEngine;
import com.hurlant.crypto.tls.TLSSecurityParameters;
import com.hurlant.crypto.tls.TLSSocket;
import flash.display.*;
import flash.events.*;
import flash.external.*;
import flash.net.*;
import flash.system.*;
import flash.utils.*;
import mx.controls.*;
import mx.core.*;
import mx.events.*;
import mx.utils.*;
public class WebSocket extends EventDispatcher {
private static var CONNECTING:int = 0;
private static var OPEN:int = 1;
private static var CLOSING:int = 2;
private static var CLOSED:int = 3;
private var id:int;
private var rawSocket:Socket;
private var tlsSocket:TLSSocket;
private var tlsConfig:TLSConfig;
private var socket:Socket;
private var url:String;
private var scheme:String;
private var host:String;
private var port:uint;
private var path:String;
private var origin:String;
private var requestedProtocols:Array;
private var acceptedProtocol:String;
private var buffer:ByteArray = new ByteArray();
private var headerState:int = 0;
private var readyState:int = CONNECTING;
private var cookie:String;
private var headers:String;
private var noiseChars:Array;
private var expectedDigest:String;
private var logger:IWebSocketLogger;
public function WebSocket(
id:int, url:String, protocols:Array, origin:String,
proxyHost:String, proxyPort:int,
cookie:String, headers:String,
logger:IWebSocketLogger) {
this.logger = logger;
this.id = id;
initNoiseChars();
this.url = url;
var m:Array = url.match(/^(\w+):\/\/([^\/:]+)(:(\d+))?(\/.*)?(\?.*)?$/);
if (!m) fatal("SYNTAX_ERR: invalid url: " + url);
this.scheme = m[1];
this.host = m[2];
var defaultPort:int = scheme == "wss" ? 443 : 80;
this.port = parseInt(m[4]) || defaultPort;
this.path = (m[5] || "/") + (m[6] || "");
this.origin = origin;
this.requestedProtocols = protocols;
this.cookie = cookie;
// if present and not the empty string, headers MUST end with \r\n
// headers should be zero or more complete lines, for example
// "Header1: xxx\r\nHeader2: yyyy\r\n"
this.headers = headers;
if (proxyHost != null && proxyPort != 0){
if (scheme == "wss") {
fatal("wss with proxy is not supported");
}
var proxySocket:RFC2817Socket = new RFC2817Socket();
proxySocket.setProxyInfo(proxyHost, proxyPort);
proxySocket.addEventListener(ProgressEvent.SOCKET_DATA, onSocketData);
rawSocket = socket = proxySocket;
} else {
rawSocket = new Socket();
if (scheme == "wss") {
tlsConfig= new TLSConfig(TLSEngine.CLIENT,
null, null, null, null, null,
TLSSecurityParameters.PROTOCOL_VERSION);
tlsConfig.trustAllCertificates = true;
tlsConfig.ignoreCommonNameMismatch = true;
tlsSocket = new TLSSocket();
tlsSocket.addEventListener(ProgressEvent.SOCKET_DATA, onSocketData);
socket = tlsSocket;
} else {
rawSocket.addEventListener(ProgressEvent.SOCKET_DATA, onSocketData);
socket = rawSocket;
}
}
rawSocket.addEventListener(Event.CLOSE, onSocketClose);
rawSocket.addEventListener(Event.CONNECT, onSocketConnect);
rawSocket.addEventListener(IOErrorEvent.IO_ERROR, onSocketIoError);
rawSocket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSocketSecurityError);
rawSocket.connect(host, port);
}
/**
* @return This WebSocket's ID.
*/
public function getId():int {
return this.id;
}
/**
* @return this WebSocket's readyState.
*/
public function getReadyState():int {
return this.readyState;
}
public function getAcceptedProtocol():String {
return this.acceptedProtocol;
}
public function send(encData:String):int {
var data:String = decodeURIComponent(encData);
if (readyState == OPEN) {
socket.writeByte(0x00);
socket.writeUTFBytes(data);
socket.writeByte(0xff);
socket.flush();
logger.log("sent: " + data);
return -1;
} else if (readyState == CLOSING || readyState == CLOSED) {
var bytes:ByteArray = new ByteArray();
bytes.writeUTFBytes(data);
return bytes.length; // not sure whether it should include \x00 and \xff
} else {
fatal("invalid state");
return 0;
}
}
public function close(isError:Boolean = false):void {
logger.log("close");
try {
if (readyState == OPEN && !isError) {
socket.writeByte(0xff);
socket.writeByte(0x00);
socket.flush();
}
socket.close();
} catch (ex:Error) { }
readyState = CLOSED;
this.dispatchEvent(new WebSocketEvent(isError ? "error" : "close"));
}
private function onSocketConnect(event:Event):void {
logger.log("connected");
if (scheme == "wss") {
logger.log("starting SSL/TLS");
tlsSocket.startTLS(rawSocket, host, tlsConfig);
}
var defaultPort:int = scheme == "wss" ? 443 : 80;
var hostValue:String = host + (port == defaultPort ? "" : ":" + port);
var key1:String = generateKey();
var key2:String = generateKey();
var key3:String = generateKey3();
expectedDigest = getSecurityDigest(key1, key2, key3);
var opt:String = "";
if (requestedProtocols.length > 0) {
opt += "Sec-WebSocket-Protocol: " + requestedProtocols.join(",") + "\r\n";
}
// if caller passes additional headers they must end with "\r\n"
if (headers) opt += headers;
var req:String = StringUtil.substitute(
"GET {0} HTTP/1.1\r\n" +
"Upgrade: WebSocket\r\n" +
"Connection: Upgrade\r\n" +
"Host: {1}\r\n" +
"Origin: {2}\r\n" +
"Cookie: {3}\r\n" +
"Sec-WebSocket-Key1: {4}\r\n" +
"Sec-WebSocket-Key2: {5}\r\n" +
"{6}" +
"\r\n",
path, hostValue, origin, cookie, key1, key2, opt);
logger.log("request header:\n" + req);
socket.writeUTFBytes(req);
logger.log("sent key3: " + key3);
writeBytes(key3);
socket.flush();
}
private function onSocketClose(event:Event):void {
logger.log("closed");
readyState = CLOSED;
this.dispatchEvent(new WebSocketEvent("close"));
}
private function onSocketIoError(event:IOErrorEvent):void {
var message:String;
if (readyState == CONNECTING) {
message = "cannot connect to Web Socket server at " + url + " (IoError)";
} else {
message = "error communicating with Web Socket server at " + url + " (IoError)";
}
onError(message);
}
private function onSocketSecurityError(event:SecurityErrorEvent):void {
var message:String;
if (readyState == CONNECTING) {
message =
"cannot connect to Web Socket server at " + url + " (SecurityError)\n" +
"make sure the server is running and Flash socket policy file is correctly placed";
} else {
message = "error communicating with Web Socket server at " + url + " (SecurityError)";
}
onError(message);
}
private function onError(message:String):void {
if (readyState == CLOSED) return;
logger.error(message);
close(readyState != CONNECTING);
}
private function onSocketData(event:ProgressEvent):void {
var pos:int = buffer.length;
socket.readBytes(buffer, pos);
for (; pos < buffer.length; ++pos) {
if (headerState < 4) {
// try to find "\r\n\r\n"
if ((headerState == 0 || headerState == 2) && buffer[pos] == 0x0d) {
++headerState;
} else if ((headerState == 1 || headerState == 3) && buffer[pos] == 0x0a) {
++headerState;
} else {
headerState = 0;
}
if (headerState == 4) {
var headerStr:String = readUTFBytes(buffer, 0, pos + 1);
logger.log("response header:\n" + headerStr);
if (!validateHeader(headerStr)) return;
removeBufferBefore(pos + 1);
pos = -1;
}
} else if (headerState == 4) {
if (pos == 15) {
var replyDigest:String = readBytes(buffer, 0, 16);
logger.log("reply digest: " + replyDigest);
if (replyDigest != expectedDigest) {
onError("digest doesn't match: " + replyDigest + " != " + expectedDigest);
return;
}
headerState = 5;
removeBufferBefore(pos + 1);
pos = -1;
readyState = OPEN;
this.dispatchEvent(new WebSocketEvent("open"));
}
} else {
if (buffer[pos] == 0xff && pos > 0) {
if (buffer[0] != 0x00) {
onError("data must start with \\x00");
return;
}
var data:String = readUTFBytes(buffer, 1, pos - 1);
logger.log("received: " + data);
this.dispatchEvent(new WebSocketEvent("message", encodeURIComponent(data)));
removeBufferBefore(pos + 1);
pos = -1;
} else if (pos == 1 && buffer[0] == 0xff && buffer[1] == 0x00) { // closing
logger.log("received closing packet");
removeBufferBefore(pos + 1);
pos = -1;
close();
}
}
}
}
private function validateHeader(headerStr:String):Boolean {
var lines:Array = headerStr.split(/\r\n/);
if (!lines[0].match(/^HTTP\/1.1 101 /)) {
onError("bad response: " + lines[0]);
return false;
}
var header:Object = {};
var lowerHeader:Object = {};
for (var i:int = 1; i < lines.length; ++i) {
if (lines[i].length == 0) continue;
var m:Array = lines[i].match(/^(\S+): (.*)$/);
if (!m) {
onError("failed to parse response header line: " + lines[i]);
return false;
}
header[m[1].toLowerCase()] = m[2];
lowerHeader[m[1].toLowerCase()] = m[2].toLowerCase();
}
if (lowerHeader["upgrade"] != "websocket") {
onError("invalid Upgrade: " + header["Upgrade"]);
return false;
}
if (lowerHeader["connection"] != "upgrade") {
onError("invalid Connection: " + header["Connection"]);
return false;
}
if (!lowerHeader["sec-websocket-origin"]) {
if (lowerHeader["websocket-origin"]) {
onError(
"The WebSocket server speaks old WebSocket protocol, " +
"which is not supported by web-socket-js. " +
"It requires WebSocket protocol 76 or later. " +
"Try newer version of the server if available.");
} else {
onError("header Sec-WebSocket-Origin is missing");
}
return false;
}
var resOrigin:String = lowerHeader["sec-websocket-origin"];
if (resOrigin != origin) {
onError("origin doesn't match: '" + resOrigin + "' != '" + origin + "'");
return false;
}
if (requestedProtocols.length > 0) {
acceptedProtocol = header["sec-websocket-protocol"];
if (requestedProtocols.indexOf(acceptedProtocol) < 0) {
onError("protocol doesn't match: '" +
acceptedProtocol + "' not in '" + requestedProtocols.join(",") + "'");
return false;
}
}
return true;
}
private function removeBufferBefore(pos:int):void {
if (pos == 0) return;
var nextBuffer:ByteArray = new ByteArray();
buffer.position = pos;
buffer.readBytes(nextBuffer);
buffer = nextBuffer;
}
private function initNoiseChars():void {
noiseChars = new Array();
for (var i:int = 0x21; i <= 0x2f; ++i) {
noiseChars.push(String.fromCharCode(i));
}
for (var j:int = 0x3a; j <= 0x7a; ++j) {
noiseChars.push(String.fromCharCode(j));
}
}
private function generateKey():String {
var spaces:uint = randomInt(1, 12);
var max:uint = uint.MAX_VALUE / spaces;
var number:uint = randomInt(0, max);
var key:String = (number * spaces).toString();
var noises:int = randomInt(1, 12);
var pos:int;
for (var i:int = 0; i < noises; ++i) {
var char:String = noiseChars[randomInt(0, noiseChars.length - 1)];
pos = randomInt(0, key.length);
key = key.substr(0, pos) + char + key.substr(pos);
}
for (var j:int = 0; j < spaces; ++j) {
pos = randomInt(1, key.length - 1);
key = key.substr(0, pos) + " " + key.substr(pos);
}
return key;
}
private function generateKey3():String {
var key3:String = "";
for (var i:int = 0; i < 8; ++i) {
key3 += String.fromCharCode(randomInt(0, 255));
}
return key3;
}
private function getSecurityDigest(key1:String, key2:String, key3:String):String {
var bytes1:String = keyToBytes(key1);
var bytes2:String = keyToBytes(key2);
return MD5.rstr_md5(bytes1 + bytes2 + key3);
}
private function keyToBytes(key:String):String {
var keyNum:uint = parseInt(key.replace(/[^\d]/g, ""));
var spaces:uint = 0;
for (var i:int = 0; i < key.length; ++i) {
if (key.charAt(i) == " ") ++spaces;
}
var resultNum:uint = keyNum / spaces;
var bytes:String = "";
for (var j:int = 3; j >= 0; --j) {
bytes += String.fromCharCode((resultNum >> (j * 8)) & 0xff);
}
return bytes;
}
// Writes byte sequence to socket.
// bytes is String in special format where bytes[i] is i-th byte, not i-th character.
private function writeBytes(bytes:String):void {
for (var i:int = 0; i < bytes.length; ++i) {
socket.writeByte(bytes.charCodeAt(i));
}
}
// Reads specified number of bytes from buffer, and returns it as special format String
// where bytes[i] is i-th byte (not i-th character).
private function readBytes(buffer:ByteArray, start:int, numBytes:int):String {
buffer.position = start;
var bytes:String = "";
for (var i:int = 0; i < numBytes; ++i) {
// & 0xff is to make \x80-\xff positive number.
bytes += String.fromCharCode(buffer.readByte() & 0xff);
}
return bytes;
}
private function readUTFBytes(buffer:ByteArray, start:int, numBytes:int):String {
buffer.position = start;
var data:String = "";
for(var i:int = start; i < start + numBytes; ++i) {
// Workaround of a bug of ByteArray#readUTFBytes() that bytes after "\x00" is discarded.
if (buffer[i] == 0x00) {
data += buffer.readUTFBytes(i - buffer.position) + "\x00";
buffer.position = i + 1;
}
}
data += buffer.readUTFBytes(start + numBytes - buffer.position);
return data;
}
private function randomInt(min:uint, max:uint):uint {
return min + Math.floor(Math.random() * (Number(max) - min + 1));
}
private function fatal(message:String):void {
logger.error(message);
throw message;
}
// for debug
private function dumpBytes(bytes:String):void {
var output:String = "";
for (var i:int = 0; i < bytes.length; ++i) {
output += bytes.charCodeAt(i).toString() + ", ";
}
logger.log(output);
}
}
}

View file

@ -1,33 +0,0 @@
package {
import flash.events.Event;
/**
* This class represents a generic websocket event. It contains the standard "type"
* parameter as well as a "message" parameter.
*/
public class WebSocketEvent extends Event {
public static const OPEN:String = "open";
public static const CLOSE:String = "close";
public static const MESSAGE:String = "message";
public static const ERROR:String = "error";
public var message:String;
public function WebSocketEvent(
type:String, message:String = null, bubbles:Boolean = false, cancelable:Boolean = false) {
super(type, bubbles, cancelable);
this.message = message;
}
public override function clone():Event {
return new WebSocketEvent(this.type, this.message, this.bubbles, this.cancelable);
}
public override function toString():String {
return "WebSocketEvent: " + this.type + ": " + this.message;
}
}
}

View file

@ -1,150 +0,0 @@
// Copyright: Hiroshi Ichikawa <http://gimite.net/en/>
// License: New BSD License
// Reference: http://dev.w3.org/html5/websockets/
// Reference: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76
package {
import flash.display.Sprite;
import flash.external.ExternalInterface;
import flash.system.Security;
import flash.utils.setTimeout;
import mx.utils.URLUtil;
/**
* Provides JavaScript API of WebSocket.
*/
public class WebSocketMain extends Sprite implements IWebSocketLogger{
private var callerUrl:String;
private var debug:Boolean = false;
private var manualPolicyFileLoaded:Boolean = false;
private var webSockets:Array = [];
private var eventQueue:Array = [];
public function WebSocketMain() {
ExternalInterface.addCallback("setCallerUrl", setCallerUrl);
ExternalInterface.addCallback("setDebug", setDebug);
ExternalInterface.addCallback("create", create);
ExternalInterface.addCallback("send", send);
ExternalInterface.addCallback("close", close);
ExternalInterface.addCallback("loadManualPolicyFile", loadManualPolicyFile);
ExternalInterface.addCallback("receiveEvents", receiveEvents);
ExternalInterface.call("WebSocket.__onFlashInitialized");
}
public function setCallerUrl(url:String):void {
callerUrl = url;
}
public function setDebug(val:Boolean):void {
debug = val;
}
private function loadDefaultPolicyFile(wsUrl:String):void {
var policyUrl:String = "xmlsocket://" + URLUtil.getServerName(wsUrl) + ":843";
log("policy file: " + policyUrl);
Security.loadPolicyFile(policyUrl);
}
public function loadManualPolicyFile(policyUrl:String):void {
log("policy file: " + policyUrl);
Security.loadPolicyFile(policyUrl);
manualPolicyFileLoaded = true;
}
public function log(message:String):void {
if (debug) {
ExternalInterface.call("WebSocket.__log", encodeURIComponent("[WebSocket] " + message));
}
}
public function error(message:String):void {
ExternalInterface.call("WebSocket.__error", encodeURIComponent("[WebSocket] " + message));
}
private function parseEvent(event:WebSocketEvent):Object {
var webSocket:WebSocket = event.target as WebSocket;
var eventObj:Object = {};
eventObj.type = event.type;
eventObj.webSocketId = webSocket.getId();
eventObj.readyState = webSocket.getReadyState();
eventObj.protocol = webSocket.getAcceptedProtocol();
if (event.message !== null) {
eventObj.message = event.message;
}
return eventObj;
}
public function create(
webSocketId:int,
url:String, protocols:Array,
proxyHost:String = null, proxyPort:int = 0,
headers:String = null):void {
if (!manualPolicyFileLoaded) {
loadDefaultPolicyFile(url);
}
var newSocket:WebSocket = new WebSocket(
webSocketId, url, protocols, getOrigin(), proxyHost, proxyPort,
getCookie(url), headers, this);
newSocket.addEventListener("open", onSocketEvent);
newSocket.addEventListener("close", onSocketEvent);
newSocket.addEventListener("error", onSocketEvent);
newSocket.addEventListener("message", onSocketEvent);
webSockets[webSocketId] = newSocket;
}
public function send(webSocketId:int, encData:String):int {
var webSocket:WebSocket = webSockets[webSocketId];
return webSocket.send(encData);
}
public function close(webSocketId:int):void {
var webSocket:WebSocket = webSockets[webSocketId];
webSocket.close();
}
public function receiveEvents():Object {
var result:Object = eventQueue;
eventQueue = [];
return result;
}
private function getOrigin():String {
return (URLUtil.getProtocol(this.callerUrl) + "://" +
URLUtil.getServerNameWithPort(this.callerUrl)).toLowerCase();
}
private function getCookie(url:String):String {
if (URLUtil.getServerName(url).toLowerCase() ==
URLUtil.getServerName(this.callerUrl).toLowerCase()) {
return ExternalInterface.call("function(){return document.cookie}");
} else {
return "";
}
}
/**
* Socket event handler.
*/
public function onSocketEvent(event:WebSocketEvent):void {
var eventObj:Object = parseEvent(event);
eventQueue.push(eventObj);
processEvents();
}
/**
* Process our event queue. If javascript is unresponsive, set
* a timeout and try again.
*/
public function processEvents():void {
if (eventQueue.length == 0) return;
if (!ExternalInterface.call("WebSocket.__onFlashEvent")) {
setTimeout(processEvents, 500);
}
}
}
}

View file

@ -1,19 +0,0 @@
// Copyright: Hiroshi Ichikawa <http://gimite.net/en/>
// License: New BSD License
// Reference: http://dev.w3.org/html5/websockets/
// Reference: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76
package {
import flash.system.*;
public class WebSocketMainInsecure extends WebSocketMain {
public function WebSocketMainInsecure() {
Security.allowDomain("*");
super();
}
}
}

View file

@ -1,10 +0,0 @@
#!/bin/sh
# You need Flex 4 SDK:
# http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+4
mxmlc -static-link-runtime-shared-libraries -target-player=10.0.0 -output=../WebSocketMain.swf WebSocketMain.as &&
mxmlc -static-link-runtime-shared-libraries -output=../WebSocketMainInsecure.swf WebSocketMainInsecure.as &&
cd .. &&
zip WebSocketMainInsecure.zip WebSocketMainInsecure.swf &&
rm WebSocketMainInsecure.swf

View file

@ -1,204 +0,0 @@
/*
Adobe Systems Incorporated(r) Source Code License Agreement
Copyright(c) 2005 Adobe Systems Incorporated. All rights reserved.
Please read this Source Code License Agreement carefully before using
the source code.
Adobe Systems Incorporated grants to you a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable copyright license, to reproduce,
prepare derivative works of, publicly display, publicly perform, and
distribute this source code and such derivative works in source or
object code form without any attribution requirements.
The name "Adobe Systems Incorporated" must not be used to endorse or promote products
derived from the source code without prior written permission.
You agree to indemnify, hold harmless and defend Adobe Systems Incorporated from and
against any loss, damage, claims or lawsuits, including attorney's
fees that arise or result from your use or distribution of the source
code.
THIS SOURCE CODE IS PROVIDED "AS IS" AND "WITH ALL FAULTS", WITHOUT
ANY TECHNICAL SUPPORT OR ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ALSO, THERE IS NO WARRANTY OF
NON-INFRINGEMENT, TITLE OR QUIET ENJOYMENT. IN NO EVENT SHALL MACROMEDIA
OR ITS SUPPLIERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOURCE CODE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.adobe.net.proxies
{
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.net.Socket;
/**
* This class allows TCP socket connections through HTTP proxies in accordance with
* RFC 2817:
*
* ftp://ftp.rfc-editor.org/in-notes/rfc2817.txt
*
* It can also be used to make direct connections to a destination, as well. If you
* pass the host and port into the constructor, no proxy will be used. You can also
* call connect, passing in the host and the port, and if you didn't set the proxy
* info, a direct connection will be made. A proxy is only used after you have called
* the setProxyInfo function.
*
* The connection to and negotiation with the proxy is completely hidden. All the
* same events are thrown whether you are using a proxy or not, and the data you
* receive from the target server will look exact as it would if you were connected
* to it directly rather than through a proxy.
*
* @author Christian Cantrell
*
**/
public class RFC2817Socket
extends Socket
{
private var proxyHost:String = null;
private var host:String = null;
private var proxyPort:int = 0;
private var port:int = 0;
private var deferredEventHandlers:Object = new Object();
private var buffer:String = new String();
/**
* Construct a new RFC2817Socket object. If you pass in the host and the port,
* no proxy will be used. If you want to use a proxy, instantiate with no
* arguments, call setProxyInfo, then call connect.
**/
public function RFC2817Socket(host:String = null, port:int = 0)
{
if (host != null && port != 0)
{
super(host, port);
}
}
/**
* Set the proxy host and port number. Your connection will only proxied if
* this function has been called.
**/
public function setProxyInfo(host:String, port:int):void
{
this.proxyHost = host;
this.proxyPort = port;
var deferredSocketDataHandler:Object = this.deferredEventHandlers[ProgressEvent.SOCKET_DATA];
var deferredConnectHandler:Object = this.deferredEventHandlers[Event.CONNECT];
if (deferredSocketDataHandler != null)
{
super.removeEventListener(ProgressEvent.SOCKET_DATA, deferredSocketDataHandler.listener, deferredSocketDataHandler.useCapture);
}
if (deferredConnectHandler != null)
{
super.removeEventListener(Event.CONNECT, deferredConnectHandler.listener, deferredConnectHandler.useCapture);
}
}
/**
* Connect to the specified host over the specified port. If you want your
* connection proxied, call the setProxyInfo function first.
**/
public override function connect(host:String, port:int):void
{
if (this.proxyHost == null)
{
this.redirectConnectEvent();
this.redirectSocketDataEvent();
super.connect(host, port);
}
else
{
this.host = host;
this.port = port;
super.addEventListener(Event.CONNECT, this.onConnect);
super.addEventListener(ProgressEvent.SOCKET_DATA, this.onSocketData);
super.connect(this.proxyHost, this.proxyPort);
}
}
private function onConnect(event:Event):void
{
this.writeUTFBytes("CONNECT "+this.host+":"+this.port+" HTTP/1.1\n\n");
this.flush();
this.redirectConnectEvent();
}
private function onSocketData(event:ProgressEvent):void
{
while (this.bytesAvailable != 0)
{
this.buffer += this.readUTFBytes(1);
if (this.buffer.search(/\r?\n\r?\n$/) != -1)
{
this.checkResponse(event);
break;
}
}
}
private function checkResponse(event:ProgressEvent):void
{
var responseCode:String = this.buffer.substr(this.buffer.indexOf(" ")+1, 3);
if (responseCode.search(/^2/) == -1)
{
var ioError:IOErrorEvent = new IOErrorEvent(IOErrorEvent.IO_ERROR);
ioError.text = "Error connecting to the proxy ["+this.proxyHost+"] on port ["+this.proxyPort+"]: " + this.buffer;
this.dispatchEvent(ioError);
}
else
{
this.redirectSocketDataEvent();
this.dispatchEvent(new Event(Event.CONNECT));
if (this.bytesAvailable > 0)
{
this.dispatchEvent(event);
}
}
this.buffer = null;
}
private function redirectConnectEvent():void
{
super.removeEventListener(Event.CONNECT, onConnect);
var deferredEventHandler:Object = this.deferredEventHandlers[Event.CONNECT];
if (deferredEventHandler != null)
{
super.addEventListener(Event.CONNECT, deferredEventHandler.listener, deferredEventHandler.useCapture, deferredEventHandler.priority, deferredEventHandler.useWeakReference);
}
}
private function redirectSocketDataEvent():void
{
super.removeEventListener(ProgressEvent.SOCKET_DATA, onSocketData);
var deferredEventHandler:Object = this.deferredEventHandlers[ProgressEvent.SOCKET_DATA];
if (deferredEventHandler != null)
{
super.addEventListener(ProgressEvent.SOCKET_DATA, deferredEventHandler.listener, deferredEventHandler.useCapture, deferredEventHandler.priority, deferredEventHandler.useWeakReference);
}
}
public override function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int=0.0, useWeakReference:Boolean=false):void
{
if (type == Event.CONNECT || type == ProgressEvent.SOCKET_DATA)
{
this.deferredEventHandlers[type] = {listener:listener,useCapture:useCapture, priority:priority, useWeakReference:useWeakReference};
}
else
{
super.addEventListener(type, listener, useCapture, priority, useWeakReference);
}
}
}
}

View file

@ -1,375 +0,0 @@
package com.gsolo.encryption {
public class MD5 {
/*
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.2-alpha Copyright (C) Paul Johnston 1999 - 2005
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for more info.
*
* Converted to AS3 By Geoffrey Williams
*/
/*
* Configurable variables. You may need to tweak these to be compatible with
* the server-side, but the defaults work in most cases.
*/
public static const HEX_FORMAT_LOWERCASE:uint = 0;
public static const HEX_FORMAT_UPPERCASE:uint = 1;
public static const BASE64_PAD_CHARACTER_DEFAULT_COMPLIANCE:String = "";
public static const BASE64_PAD_CHARACTER_RFC_COMPLIANCE:String = "=";
public static var hexcase:uint = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
public static var b64pad:String = ""; /* base-64 pad character. "=" for strict RFC compliance */
public static function encrypt (string:String):String {
return hex_md5 (string);
}
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
public static function hex_md5 (string:String):String {
return rstr2hex (rstr_md5 (str2rstr_utf8 (string)));
}
public static function b64_md5 (string:String):String {
return rstr2b64 (rstr_md5 (str2rstr_utf8 (string)));
}
public static function any_md5 (string:String, encoding:String):String {
return rstr2any (rstr_md5 (str2rstr_utf8 (string)), encoding);
}
public static function hex_hmac_md5 (key:String, data:String):String {
return rstr2hex (rstr_hmac_md5 (str2rstr_utf8 (key), str2rstr_utf8 (data)));
}
public static function b64_hmac_md5 (key:String, data:String):String {
return rstr2b64 (rstr_hmac_md5 (str2rstr_utf8 (key), str2rstr_utf8 (data)));
}
public static function any_hmac_md5 (key:String, data:String, encoding:String):String {
return rstr2any(rstr_hmac_md5(str2rstr_utf8(key), str2rstr_utf8(data)), encoding);
}
/*
* Perform a simple self-test to see if the VM is working
*/
public static function md5_vm_test ():Boolean {
return hex_md5 ("abc") == "900150983cd24fb0d6963f7d28e17f72";
}
/*
* Calculate the MD5 of a raw string
*/
public static function rstr_md5 (string:String):String {
return binl2rstr (binl_md5 (rstr2binl (string), string.length * 8));
}
/*
* Calculate the HMAC-MD5, of a key and some data (raw strings)
*/
public static function rstr_hmac_md5 (key:String, data:String):String {
var bkey:Array = rstr2binl (key);
if (bkey.length > 16) bkey = binl_md5 (bkey, key.length * 8);
var ipad:Array = new Array(16), opad:Array = new Array(16);
for(var i:Number = 0; i < 16; i++) {
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash:Array = binl_md5 (ipad.concat (rstr2binl (data)), 512 + data.length * 8);
return binl2rstr (binl_md5 (opad.concat (hash), 512 + 128));
}
/*
* Convert a raw string to a hex string
*/
public static function rstr2hex (input:String):String {
var hex_tab:String = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var output:String = "";
var x:Number;
for(var i:Number = 0; i < input.length; i++) {
x = input.charCodeAt(i);
output += hex_tab.charAt((x >>> 4) & 0x0F)
+ hex_tab.charAt( x & 0x0F);
}
return output;
}
/*
* Convert a raw string to a base-64 string
*/
public static function rstr2b64 (input:String):String {
var tab:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var output:String = "";
var len:Number = input.length;
for(var i:Number = 0; i < len; i += 3) {
var triplet:Number = (input.charCodeAt(i) << 16)
| (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
| (i + 2 < len ? input.charCodeAt(i+2) : 0);
for(var j:Number = 0; j < 4; j++) {
if(i * 8 + j * 6 > input.length * 8) output += b64pad;
else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
}
}
return output;
}
/*
* Convert a raw string to an arbitrary string encoding
*/
public static function rstr2any(input:String, encoding:String):String {
var divisor:Number = encoding.length;
var remainders:Array = [];
var i:Number, q:Number, x:Number, quotient:Array;
/* Convert to an array of 16-bit big-endian values, forming the dividend */
var dividend:Array = new Array(input.length / 2);
for(i = 0; i < dividend.length; i++) {
dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
}
/*
* Repeatedly perform a long division. The binary array forms the dividend,
* the length of the encoding is the divisor. Once computed, the quotient
* forms the dividend for the next step. We stop when the dividend is zero.
* All remainders are stored for later use.
*/
while(dividend.length > 0) {
quotient = [];
x = 0;
for(i = 0; i < dividend.length; i++) {
x = (x << 16) + dividend[i];
q = Math.floor(x / divisor);
x -= q * divisor;
if(quotient.length > 0 || q > 0)
quotient[quotient.length] = q;
}
remainders[remainders.length] = x;
dividend = quotient;
}
/* Convert the remainders to the output string */
var output:String = "";
for(i = remainders.length - 1; i >= 0; i--)
output += encoding.charAt (remainders[i]);
return output;
}
/*
* Encode a string as utf-8.
* For efficiency, this assumes the input is valid utf-16.
*/
public static function str2rstr_utf8 (input:String):String {
var output:String = "";
var i:Number = -1;
var x:Number, y:Number;
while(++i < input.length) {
/* Decode utf-16 surrogate pairs */
x = input.charCodeAt(i);
y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) {
x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
i++;
}
/* Encode output as utf-8 */
if(x <= 0x7F)
output += String.fromCharCode(x);
else if(x <= 0x7FF)
output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
0x80 | ( x & 0x3F));
else if(x <= 0xFFFF)
output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
0x80 | ((x >>> 6 ) & 0x3F),
0x80 | ( x & 0x3F));
else if(x <= 0x1FFFFF)
output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
0x80 | ((x >>> 12) & 0x3F),
0x80 | ((x >>> 6 ) & 0x3F),
0x80 | ( x & 0x3F));
}
return output;
}
/*
* Encode a string as utf-16
*/
public static function str2rstr_utf16le (input:String):String {
var output:String = "";
for(var i:Number = 0; i < input.length; i++)
output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
(input.charCodeAt(i) >>> 8) & 0xFF);
return output;
}
public static function str2rstr_utf16be (input:String):String {
var output:String = "";
for(var i:Number = 0; i < input.length; i++)
output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
input.charCodeAt(i) & 0xFF);
return output;
}
/*
* Convert a raw string to an array of little-endian words
* Characters >255 have their high-byte silently ignored.
*/
public static function rstr2binl (input:String):Array {
var output:Array = new Array(input.length >> 2);
for(var i:Number = 0; i < output.length; i++)
output[i] = 0;
for(i = 0; i < input.length * 8; i += 8)
output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
return output;
}
/*
* Convert an array of little-endian words to a string
*/
public static function binl2rstr (input:Array):String {
var output:String = "";
for(var i:Number = 0; i < input.length * 32; i += 8)
output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
return output;
}
/*
* Calculate the MD5 of an array of little-endian words, and a bit length.
*/
public static function binl_md5 (x:Array, len:Number):Array {
/* append padding */
x[len >> 5] |= 0x80 << ((len) % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;
var a:Number = 1732584193;
var b:Number = -271733879;
var c:Number = -1732584194;
var d:Number = 271733878;
for(var i:Number = 0; i < x.length; i += 16) {
var olda:Number = a;
var oldb:Number = b;
var oldc:Number = c;
var oldd:Number = d;
a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
}
return [a, b, c, d];
}
/*
* These functions implement the four basic operations the algorithm uses.
*/
public static function md5_cmn (q:Number, a:Number, b:Number, x:Number, s:Number, t:Number):Number {
return safe_add (bit_rol (safe_add (safe_add (a, q), safe_add(x, t)), s), b);
}
public static function md5_ff (a:Number, b:Number, c:Number, d:Number, x:Number, s:Number, t:Number):Number {
return md5_cmn ((b & c) | ((~b) & d), a, b, x, s, t);
}
public static function md5_gg (a:Number, b:Number, c:Number, d:Number, x:Number, s:Number, t:Number):Number {
return md5_cmn ((b & d) | (c & (~d)), a, b, x, s, t);
}
public static function md5_hh (a:Number, b:Number, c:Number, d:Number, x:Number, s:Number, t:Number):Number {
return md5_cmn (b ^ c ^ d, a, b, x, s, t);
}
public static function md5_ii (a:Number, b:Number, c:Number, d:Number, x:Number, s:Number, t:Number):Number {
return md5_cmn (c ^ (b | (~d)), a, b, x, s, t);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
public static function safe_add (x:Number, y:Number):Number {
var lsw:Number = (x & 0xFFFF) + (y & 0xFFFF);
var msw:Number = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
public static function bit_rol (num:Number, cnt:Number):Number {
return (num << cnt) | (num >>> (32 - cnt));
}
}
}

View file

@ -1,287 +0,0 @@
/**
* Crypto
*
* An abstraction layer to instanciate our crypto algorithms
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto
{
import com.hurlant.crypto.hash.HMAC;
import com.hurlant.crypto.hash.MAC;
import com.hurlant.crypto.hash.IHash;
import com.hurlant.crypto.hash.MD2;
import com.hurlant.crypto.hash.MD5;
import com.hurlant.crypto.hash.SHA1;
import com.hurlant.crypto.hash.SHA224;
import com.hurlant.crypto.hash.SHA256;
import com.hurlant.crypto.prng.ARC4;
import com.hurlant.crypto.rsa.RSAKey;
import com.hurlant.crypto.symmetric.AESKey;
import com.hurlant.crypto.symmetric.BlowFishKey;
import com.hurlant.crypto.symmetric.CBCMode;
import com.hurlant.crypto.symmetric.CFB8Mode;
import com.hurlant.crypto.symmetric.CFBMode;
import com.hurlant.crypto.symmetric.CTRMode;
import com.hurlant.crypto.symmetric.DESKey;
import com.hurlant.crypto.symmetric.ECBMode;
import com.hurlant.crypto.symmetric.ICipher;
import com.hurlant.crypto.symmetric.IMode;
import com.hurlant.crypto.symmetric.IPad;
import com.hurlant.crypto.symmetric.ISymmetricKey;
import com.hurlant.crypto.symmetric.IVMode;
import com.hurlant.crypto.symmetric.NullPad;
import com.hurlant.crypto.symmetric.OFBMode;
import com.hurlant.crypto.symmetric.PKCS5;
import com.hurlant.crypto.symmetric.SimpleIVMode;
import com.hurlant.crypto.symmetric.TripleDESKey;
import com.hurlant.crypto.symmetric.XTeaKey;
import com.hurlant.util.Base64;
import flash.utils.ByteArray;
/**
* A class to make it easy to use the rest of the framework.
* As a side-effect, using this class will cause most of the framework
* to be linked into your application, which is not always what you want.
*
* If you want to optimize your download size, don't use this class.
* (But feel free to read it to get ideas on how to get the algorithm you want.)
*/
public class Crypto
{
private var b64:Base64; // we don't use it, but we want the swc to include it, so cheap trick.
public function Crypto(){
}
/**
* Things that should work, among others:
* "aes"
* "aes-128-ecb"
* "aes-128-cbc"
* "aes-128-cfb"
* "aes-128-cfb8"
* "aes-128-ofb"
* "aes-192-cfb"
* "aes-256-ofb"
* "blowfish-cbc"
* "des-ecb"
* "xtea"
* "xtea-ecb"
* "xtea-cbc"
* "xtea-cfb"
* "xtea-cfb8"
* "xtea-ofb"
* "rc4"
* "simple-aes-cbc"
*/
public static function getCipher(name:String, key:ByteArray, pad:IPad=null):ICipher {
// split name into an array.
var keys:Array = name.split("-");
switch (keys[0]) {
/**
* "simple" is a special case. It means:
* "If using an IV mode, prepend the IV to the ciphertext"
*/
case "simple":
keys.shift();
name = keys.join("-");
var cipher:ICipher = getCipher(name, key, pad);
if (cipher is IVMode) {
return new SimpleIVMode(cipher as IVMode);
} else {
return cipher;
}
/**
* we support both "aes-128" and "aes128"
* Technically, you could use "aes192-128", but you'd
* only be hurting yourself.
*/
case "aes":
case "aes128":
case "aes192":
case "aes256":
keys.shift();
if (key.length*8==keys[0]) {
// support for "aes-128-..." and such.
keys.shift();
}
return getMode(keys[0], new AESKey(key), pad);
break;
case "bf":
case "blowfish":
keys.shift();
return getMode(keys[0], new BlowFishKey(key), pad);
/**
* des-ede and des-ede3 are both equivalent to des3.
* the choice between 2tdes and 3tdes is made based
* on the length of the key provided.
*/
case "des":
keys.shift();
if (keys[0]!="ede" && keys[0]!="ede3") {
return getMode(keys[0], new DESKey(key), pad);
}
if (keys.length==1) {
keys.push("ecb"); // default mode for 2tdes and 3tdes with openssl enc
}
// fall-through to triple des
case "3des":
case "des3":
keys.shift();
return getMode(keys[0], new TripleDESKey(key), pad);
case "xtea":
keys.shift();
return getMode(keys[0], new XTeaKey(key), pad);
break;
/**
* Technically, you could say "rc4-128" or whatever,
* but really, the length of the key is what counts here.
*/
case "rc4":
keys.shift();
return new ARC4(key);
break;
}
return null;
}
/**
* Returns the size of a key for a given cipher identifier.
*/
public static function getKeySize(name:String):uint {
var keys:Array = name.split("-");
switch (keys[0]) {
case "simple":
keys.shift();
return getKeySize(keys.join("-"));
case "aes128":
return 16;
case "aes192":
return 24;
case "aes256":
return 32;
case "aes":
keys.shift();
return parseInt(keys[0])/8;
case "bf":
case "blowfish":
return 16;
case "des":
keys.shift();
switch (keys[0]) {
case "ede":
return 16;
case "ede3":
return 24;
default:
return 8;
}
case "3des":
case "des3":
return 24;
case "xtea":
return 8;
case "rc4":
if (parseInt(keys[1])>0) {
return parseInt(keys[1])/8;
}
return 16; // why not.
}
return 0; // unknown;
}
private static function getMode(name:String, alg:ISymmetricKey, padding:IPad=null):IMode {
switch (name) {
case "ecb":
return new ECBMode(alg, padding);
case "cfb":
return new CFBMode(alg, padding);
case "cfb8":
return new CFB8Mode(alg, padding);
case "ofb":
return new OFBMode(alg, padding);
case "ctr":
return new CTRMode(alg, padding);
case "cbc":
default:
return new CBCMode(alg, padding);
}
}
/**
* Things that should work:
* "md5"
* "sha"
* "sha1"
* "sha224"
* "sha256"
*/
public static function getHash(name:String):IHash {
switch(name) {
case "md2":
return new MD2;
case "md5":
return new MD5;
case "sha": // let's hope you didn't mean sha-0
case "sha1":
return new SHA1;
case "sha224":
return new SHA224;
case "sha256":
return new SHA256;
}
return null;
}
/**
* Things that should work:
* "sha1"
* "md5-64"
* "hmac-md5-96"
* "hmac-sha1-128"
* "hmac-sha256-192"
* etc.
*/
public static function getHMAC(name:String):HMAC {
var keys:Array = name.split("-");
if (keys[0]=="hmac") keys.shift();
var bits:uint = 0;
if (keys.length>1) {
bits = parseInt(keys[1]);
}
return new HMAC(getHash(keys[0]), bits);
}
public static function getMAC(name:String):MAC {
var keys:Array = name.split("-");
if (keys[0]=="mac") keys.shift();
var bits:uint = 0;
if (keys.length > 1) {
bits = parseInt(keys[1]);
}
return new MAC(getHash(keys[0]), bits);
}
public static function getPad(name:String):IPad {
switch(name) {
case "null":
return new NullPad;
case "pkcs5":
default:
return new PKCS5;
}
}
/** mostly useless.
*/
public static function getRSA(E:String, M:String):RSAKey {
return RSAKey.parsePublicKey(M,E);
}
}
}

View file

@ -1,218 +0,0 @@
/**
* X509Certificate
*
* A representation for a X509 Certificate, with
* methods to parse, verify and sign it.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.cert {
import com.hurlant.crypto.hash.IHash;
import com.hurlant.crypto.hash.MD2;
import com.hurlant.crypto.hash.MD5;
import com.hurlant.crypto.hash.SHA1;
import com.hurlant.crypto.rsa.RSAKey;
import com.hurlant.util.ArrayUtil;
import com.hurlant.util.Base64;
import com.hurlant.util.der.ByteString;
import com.hurlant.util.der.DER;
import com.hurlant.util.der.OID;
import com.hurlant.util.der.ObjectIdentifier;
import com.hurlant.util.der.PEM;
import com.hurlant.util.der.PrintableString;
import com.hurlant.util.der.Sequence;
import com.hurlant.util.der.Type;
import flash.utils.ByteArray;
public class X509Certificate {
private var _loaded:Boolean;
private var _param:*;
private var _obj:Object;
public function X509Certificate(p:*) {
_loaded = false;
_param = p;
// lazy initialization, to avoid unnecessary parsing of every builtin CA at start-up.
}
private function load():void {
if (_loaded) return;
var p:* = _param;
var b:ByteArray;
if (p is String) {
b = PEM.readCertIntoArray(p as String);
} else if (p is ByteArray) {
b = p;
}
if (b!=null) {
_obj = DER.parse(b, Type.TLS_CERT);
_loaded = true;
} else {
throw new Error("Invalid x509 Certificate parameter: "+p);
}
}
public function isSigned(store:X509CertificateCollection, CAs:X509CertificateCollection, time:Date=null):Boolean {
load();
// check timestamps first. cheapest.
if (time==null) {
time = new Date;
}
var notBefore:Date = getNotBefore();
var notAfter:Date = getNotAfter();
if (time.getTime()<notBefore.getTime()) return false; // cert isn't born yet.
if (time.getTime()>notAfter.getTime()) return false; // cert died of old age.
// check signature.
var subject:String = getIssuerPrincipal();
// try from CA first, since they're treated better.
var parent:X509Certificate = CAs.getCertificate(subject);
var parentIsAuthoritative:Boolean = false;
if (parent == null) {
parent = store.getCertificate(subject);
if (parent == null) {
return false; // issuer not found
}
} else {
parentIsAuthoritative = true;
}
if (parent == this) { // pathological case. avoid infinite loop
return false; // isSigned() returns false if we're self-signed.
}
if (!(parentIsAuthoritative&&parent.isSelfSigned(time)) &&
!parent.isSigned(store, CAs, time)) {
return false;
}
var key:RSAKey = parent.getPublicKey();
return verifyCertificate(key);
}
public function isSelfSigned(time:Date):Boolean {
load();
var key:RSAKey = getPublicKey();
return verifyCertificate(key);
}
private function verifyCertificate(key:RSAKey):Boolean {
var algo:String = getAlgorithmIdentifier();
var hash:IHash;
var oid:String;
switch (algo) {
case OID.SHA1_WITH_RSA_ENCRYPTION:
hash = new SHA1;
oid = OID.SHA1_ALGORITHM;
break;
case OID.MD2_WITH_RSA_ENCRYPTION:
hash = new MD2;
oid = OID.MD2_ALGORITHM;
break;
case OID.MD5_WITH_RSA_ENCRYPTION:
hash = new MD5;
oid = OID.MD5_ALGORITHM;
break;
default:
return false;
}
var data:ByteArray = _obj.signedCertificate_bin;
var buf:ByteArray = new ByteArray;
key.verify(_obj.encrypted, buf, _obj.encrypted.length);
buf.position=0;
data = hash.hash(data);
var obj:Object = DER.parse(buf, Type.RSA_SIGNATURE);
if (obj.algorithm.algorithmId.toString() != oid) {
return false; // wrong algorithm
}
if (!ArrayUtil.equals(obj.hash, data)) {
return false; // hashes don't match
}
return true;
}
/**
* This isn't used anywhere so far.
* It would become useful if we started to offer facilities
* to generate and sign X509 certificates.
*
* @param key
* @param algo
* @return
*
*/
private function signCertificate(key:RSAKey, algo:String):ByteArray {
var hash:IHash;
var oid:String;
switch (algo) {
case OID.SHA1_WITH_RSA_ENCRYPTION:
hash = new SHA1;
oid = OID.SHA1_ALGORITHM;
break;
case OID.MD2_WITH_RSA_ENCRYPTION:
hash = new MD2;
oid = OID.MD2_ALGORITHM;
break;
case OID.MD5_WITH_RSA_ENCRYPTION:
hash = new MD5;
oid = OID.MD5_ALGORITHM;
break;
default:
return null
}
var data:ByteArray = _obj.signedCertificate_bin;
data = hash.hash(data);
var seq1:Sequence = new Sequence;
seq1[0] = new Sequence;
seq1[0][0] = new ObjectIdentifier(0,0, oid);
seq1[0][1] = null;
seq1[1] = new ByteString;
seq1[1].writeBytes(data);
data = seq1.toDER();
var buf:ByteArray = new ByteArray;
key.sign(data, buf, data.length);
return buf;
}
public function getPublicKey():RSAKey {
load();
var pk:ByteArray = _obj.signedCertificate.subjectPublicKeyInfo.subjectPublicKey as ByteArray;
pk.position = 0;
var rsaKey:Object = DER.parse(pk, [{name:"N"},{name:"E"}]);
return new RSAKey(rsaKey.N, rsaKey.E.valueOf());
}
/**
* Returns a subject principal, as an opaque base64 string.
* This is only used as a hash key for known certificates.
*
* Note that this assumes X509 DER-encoded certificates are uniquely encoded,
* as we look for exact matches between Issuer and Subject fields.
*
*/
public function getSubjectPrincipal():String {
load();
return Base64.encodeByteArray(_obj.signedCertificate.subject_bin);
}
/**
* Returns an issuer principal, as an opaque base64 string.
* This is only used to quickly find matching parent certificates.
*
* Note that this assumes X509 DER-encoded certificates are uniquely encoded,
* as we look for exact matches between Issuer and Subject fields.
*
*/
public function getIssuerPrincipal():String {
load();
return Base64.encodeByteArray(_obj.signedCertificate.issuer_bin);
}
public function getAlgorithmIdentifier():String {
return _obj.algorithmIdentifier.algorithmId.toString();
}
public function getNotBefore():Date {
return _obj.signedCertificate.validity.notBefore.date;
}
public function getNotAfter():Date {
return _obj.signedCertificate.validity.notAfter.date;
}
public function getCommonName():String {
var subject:Sequence = _obj.signedCertificate.subject;
return (subject.findAttributeValue(OID.COMMON_NAME) as PrintableString).getString();
}
}
}

View file

@ -1,57 +0,0 @@
/**
* X509CertificateCollection
*
* A class to store and index X509 Certificates by Subject.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.cert {
public class X509CertificateCollection {
private var _map:Object;
public function X509CertificateCollection() {
_map = {};
}
/**
* Mostly meant for built-in CA loading.
* This entry-point allows to index CAs without parsing them.
*
* @param name A friendly name. not currently used
* @param subject base64 DER encoded Subject principal for the Cert
* @param pem PEM encoded certificate data
*
*/
public function addPEMCertificate(name:String, subject:String, pem:String):void {
_map[subject] = new X509Certificate(pem);
}
/**
* Adds a X509 certificate to the collection.
* This call will force the certificate to be parsed.
*
* @param cert A X509 certificate
*
*/
public function addCertificate(cert:X509Certificate):void {
var subject:String = cert.getSubjectPrincipal();
_map[subject] = cert;
}
/**
* Returns a X509 Certificate present in the collection, given
* a base64 DER encoded X500 Subject principal
*
* @param subject A Base64 DER-encoded Subject principal
* @return A matching certificate, or null.
*
*/
public function getCertificate(subject:String):X509Certificate {
return _map[subject];
}
}
}

View file

@ -1,82 +0,0 @@
/**
* HMAC
*
* An ActionScript 3 implementation of HMAC, Keyed-Hashing for Message
* Authentication, as defined by RFC-2104
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
import com.hurlant.util.Hex;
public class HMAC implements IHMAC
{
private var hash:IHash;
private var bits:uint;
/**
* Create a HMAC object, using a Hash function, and
* optionally a number of bits to return.
* The HMAC will be truncated to that size if needed.
*/
public function HMAC(hash:IHash, bits:uint=0) {
this.hash = hash;
this.bits = bits;
}
public function getHashSize():uint {
if (bits!=0) {
return bits/8;
} else {
return hash.getHashSize();
}
}
/**
* Compute a HMAC using a key and some data.
* It doesn't modify either, and returns a new ByteArray with the HMAC value.
*/
public function compute(key:ByteArray, data:ByteArray):ByteArray {
var hashKey:ByteArray;
if (key.length>hash.getInputSize()) {
hashKey = hash.hash(key);
} else {
hashKey = new ByteArray;
hashKey.writeBytes(key);
}
while (hashKey.length<hash.getInputSize()) {
hashKey[hashKey.length]=0;
}
var innerKey:ByteArray = new ByteArray;
var outerKey:ByteArray = new ByteArray;
for (var i:uint=0;i<hashKey.length;i++) {
innerKey[i] = hashKey[i] ^ 0x36;
outerKey[i] = hashKey[i] ^ 0x5c;
}
// inner + data
innerKey.position = hashKey.length;
innerKey.writeBytes(data);
var innerHash:ByteArray = hash.hash(innerKey);
// outer + innerHash
outerKey.position = hashKey.length;
outerKey.writeBytes(innerHash);
var outerHash:ByteArray = hash.hash(outerKey);
if (bits>0 && bits<8*outerHash.length) {
outerHash.length = bits/8;
}
return outerHash;
}
public function dispose():void {
hash = null;
bits = 0;
}
public function toString():String {
return "hmac-"+(bits>0?bits+"-":"")+hash.toString();
}
}
}

View file

@ -1,27 +0,0 @@
/**
* HMAC
*
* An ActionScript 3 interface for HMAC & MAC
* implementations.
*
* Loosely copyrighted by Bobby Parker
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
public interface IHMAC
{
function getHashSize():uint;
/**
* Compute a HMAC using a key and some data.
* It doesn't modify either, and returns a new ByteArray with the HMAC value.
*/
function compute(key:ByteArray, data:ByteArray):ByteArray;
function dispose():void;
function toString():String;
}
}

View file

@ -1,21 +0,0 @@
/**
* IHash
*
* An interface for each hash function to implement
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
public interface IHash
{
function getInputSize():uint;
function getHashSize():uint;
function hash(src:ByteArray):ByteArray;
function toString():String;
function getPadSize():int;
}
}

View file

@ -1,137 +0,0 @@
/**
* MAC
*
* An ActionScript 3 implementation of MAC, Message Authentication Code
* for use with SSL 3.0.
* Loosely copyrighted by Bobby Parker.
* As3crypto copyrighted by Henri Torgemane.
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
import com.hurlant.util.Hex;
public class MAC implements IHMAC
{
private var hash:IHash;
private var bits:uint;
private var pad_1:ByteArray;
private var pad_2:ByteArray;
private var innerHash:ByteArray;
private var outerHash:ByteArray;
private var outerKey:ByteArray;
private var innerKey:ByteArray;
/**
* Create a MAC object (for SSL 3.0 ) and
* optionally a number of bits to return.
* The MAC will be truncated to that size if needed.
*/
public function MAC(hash:IHash, bits:uint=0) {
this.hash = hash;
this.bits = bits;
innerHash = new ByteArray();
outerHash = new ByteArray();
innerKey = new ByteArray();
outerKey = new ByteArray();
if (hash != null) {
var pad_size:int = hash.getPadSize();
pad_1 = new ByteArray();
pad_2 = new ByteArray();
for (var x:int = 0; x < pad_size; x++) {
pad_1.writeByte(0x36);
pad_2.writeByte(0x5c);
}
}
}
public function setPadSize(pad_size:int) : void { }
public function getHashSize():uint {
if (bits!=0) {
return bits/8;
} else {
return hash.getHashSize();
}
}
/**
* Compute a MAC using a key and some data.
*
*/
public function compute(key:ByteArray, data:ByteArray):ByteArray {
// take that incoming key and do hash(key + pad_2 + hash(key + pad_1 + sequence + length + record)
// note that data = (sequence + type + length + record)
if (pad_1 == null) {
var pad_size:int = hash.getPadSize();
pad_1 = new ByteArray();
pad_2 = new ByteArray();
for (var x:int = 0; x < pad_size; x++) {
pad_1.writeByte(0x36);
pad_2.writeByte(0x5c);
}
}
// Do some preliminary checking on stuff
/*
if (key.length > hash.getInputSize()) {
hashKey = hash.hash(key);
} else {
hashKey = new ByteArray;
hashKey.writeBytes(key);
}
while (hashKey.length < hash.getInputSize() ) {
hashKey[hashKey.length] = 0;
} */
// Henri's conventions work just fine here..
innerKey.length = 0;
outerKey.length = 0;
// trace("MAC Key: " + Hex.fromArray(key));
// trace("Key Length: " + key.length);
// trace("Pad_1 : " + Hex.fromArray(pad_1));
// inner hash calc
innerKey.writeBytes(key);
innerKey.writeBytes(pad_1);
innerKey.writeBytes(data);
// trace("MAC Inner Key: " + Hex.fromArray(innerKey));
innerHash = hash.hash(innerKey);
// trace("MAC Inner Hash: " + Hex.fromArray(innerHash));
// outer hash calc
outerKey.writeBytes(key);
outerKey.writeBytes(pad_2);
outerKey.writeBytes(innerHash);
// trace("MAC Outer Key: " + Hex.fromArray(outerKey));
outerHash = hash.hash(outerKey);
if (bits > 0 && bits < 8*outerHash.length) {
outerHash.length = bits/8;
}
// trace("MAC for record: " + Hex.fromArray(outerHash));
return outerHash;
}
public function dispose():void {
hash = null;
bits = 0;
}
public function toString():String {
return "mac-"+(bits>0?bits+"-":"")+hash.toString();
}
}
}

View file

@ -1,124 +0,0 @@
/**
* MD2
*
* An ActionScript 3 implementation of the RSA Data Security, Inc MD2 Message
* Digest Algorithm, as defined in RFC 1319
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*
* Excerpt from http://en.wikipedia.org/wiki/MD2:
* >
* > Rogier and Chauvaud (1997) described collisions of MD2's compression function,
* > although they were unable to extend the attack to the full MD2.
* >
* > In 2004, MD2 was shown to be vulnerable to a preimage attack with time
* > complexity equivalent to 2104 applications of the compression function
* > (Muller, 2004).
* > The author concludes, "MD2 can no longer be considered a secure one-way
* > hash function".
*
* also, this implementaton is quite slow.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
public class MD2 implements IHash
{
public static const HASH_SIZE:int = 16;
public var pad_size:int = 48; // probably will never get used, only here for SSL 3.0 support
private static const S:Array = [ // PI Digits
41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, 19,
98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, 76, 130, 202,
30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, 138, 23, 229, 18,
190, 78, 196, 214, 218, 158, 222, 73, 160, 251, 245, 142, 187, 47, 238, 122,
169, 104, 121, 145, 21, 178, 7, 63, 148, 194, 16, 137, 11, 34, 95, 33,
128, 127, 93, 154, 90, 144, 50, 39, 53, 62, 204, 231, 191, 247, 151, 3,
255, 25, 48, 179, 72, 165, 181, 209, 215, 94, 146, 42, 172, 86, 170, 198,
79, 184, 56, 210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241,
69, 157, 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2,
27, 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, 234, 38,
44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, 129, 77, 82,
106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, 8, 12, 189, 177, 74,
120, 136, 149, 139, 227, 99, 232, 109, 233, 203, 213, 254, 59, 0, 29, 57,
242, 239, 183, 14, 102, 88, 208, 228, 166, 119, 114, 248, 235, 117, 75, 10,
49, 68, 80, 180, 143, 237, 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 ];
public function MD2() { }
public function getInputSize():uint
{
return 16;
}
public function getPadSize():int {
return pad_size;
}
public function getHashSize():uint
{
return HASH_SIZE;
}
public function hash(src:ByteArray):ByteArray
{
var savedLength:uint = src.length;
// 3.1 Step 1. Padding
var i:uint = (16-src.length%16) || 16;
do {
src[src.length]=i;
} while (src.length%16!=0);
// 3.2 Step 2. Checksum
var len:uint = src.length;
var checksum:ByteArray = new ByteArray;
var L:uint = 0;
for (i = 0;i<len;i+=16) {
for (var j:uint=0;j<16;j++) {
L = checksum[j] ^= S[src[i+j] ^ L];
}
}
src.position = src.length;
src.writeBytes(checksum);
len += 16;
// 3.3 Step 3. MD Buffer
var X:ByteArray = new ByteArray;
// 3.4 Process Message
for (i=0;i<len;i+=16) {
/* Copy block i into X */
for (j=0;j<16;j++) {
X[32+j] = (X[16+j] = src[i+j])^X[j];
}
var t:uint=0;
/* Do 18 rounds */
for (j=0;j<18;j++) {
/* Round j. */
for (var k:uint=0;k<48;k++) {
X[k] = t = X[k]^S[t];
}
t = (t+j)&0xff;
}
}
// 3.5 Step 5. Output
X.length = 16;
// restore original length;
src.length = savedLength;
return X;
}
public function toString():String
{
return "md2";
}
}
}

View file

@ -1,204 +0,0 @@
/**
* MD5
*
* An ActionScript 3 implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Copyright (c) 2007 Henri Torgemane
*
* Derived from
* A JavaScript implementation of the same.
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
*
* Note:
* This algorithm should not be your first choice for new developements, but is
* included to allow interoperability with existing codes and protocols.
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
import flash.utils.Endian;
public class MD5 implements IHash
{
public static const HASH_SIZE:int = 16;
public var pad_size:int = 48;
public function MD5() { }
public function getInputSize():uint
{
return 64;
}
public function getHashSize():uint
{
return HASH_SIZE;
}
public function getPadSize():int
{
return pad_size;
}
public function hash(src:ByteArray):ByteArray
{
var len:uint = src.length *8;
var savedEndian:String = src.endian;
// pad to nearest int.
while (src.length%4!=0) {
src[src.length]=0;
}
// convert ByteArray to an array of uint
src.position=0;
var a:Array = [];
src.endian=Endian.LITTLE_ENDIAN
for (var i:uint=0;i<src.length;i+=4) {
a.push(src.readUnsignedInt());
}
var h:Array = core_md5(a, len);
var out:ByteArray = new ByteArray;
out.endian=Endian.LITTLE_ENDIAN;
for (i=0;i<4;i++) {
out.writeUnsignedInt(h[i]);
}
// restore length!
src.length = len/8;
src.endian = savedEndian;
return out;
}
private function core_md5(x:Array, len:uint):Array {
/* append padding */
x[len >> 5] |= 0x80 << ((len) % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;
var a:uint = 0x67452301; // 1732584193;
var b:uint = 0xEFCDAB89; //-271733879;
var c:uint = 0x98BADCFE; //-1732584194;
var d:uint = 0x10325476; // 271733878;
for(var i:uint = 0; i < x.length; i += 16)
{
x[i]||=0; x[i+1]||=0; x[i+2]||=0; x[i+3]||=0;
x[i+4]||=0; x[i+5]||=0; x[i+6]||=0; x[i+7]||=0;
x[i+8]||=0; x[i+9]||=0; x[i+10]||=0; x[i+11]||=0;
x[i+12]||=0; x[i+13]||=0; x[i+14]||=0; x[i+15]||=0;
var olda:uint = a;
var oldb:uint = b;
var oldc:uint = c;
var oldd:uint = d;
a = ff(a, b, c, d, x[i+ 0], 7 , 0xD76AA478);
d = ff(d, a, b, c, x[i+ 1], 12, 0xE8C7B756);
c = ff(c, d, a, b, x[i+ 2], 17, 0x242070DB);
b = ff(b, c, d, a, x[i+ 3], 22, 0xC1BDCEEE);
a = ff(a, b, c, d, x[i+ 4], 7 , 0xF57C0FAF);
d = ff(d, a, b, c, x[i+ 5], 12, 0x4787C62A);
c = ff(c, d, a, b, x[i+ 6], 17, 0xA8304613);
b = ff(b, c, d, a, x[i+ 7], 22, 0xFD469501);
a = ff(a, b, c, d, x[i+ 8], 7 , 0x698098D8);
d = ff(d, a, b, c, x[i+ 9], 12, 0x8B44F7AF);
c = ff(c, d, a, b, x[i+10], 17, 0xFFFF5BB1);
b = ff(b, c, d, a, x[i+11], 22, 0x895CD7BE);
a = ff(a, b, c, d, x[i+12], 7 , 0x6B901122);
d = ff(d, a, b, c, x[i+13], 12, 0xFD987193);
c = ff(c, d, a, b, x[i+14], 17, 0xA679438E);
b = ff(b, c, d, a, x[i+15], 22, 0x49B40821);
a = gg(a, b, c, d, x[i+ 1], 5 , 0xf61e2562);
d = gg(d, a, b, c, x[i+ 6], 9 , 0xc040b340);
c = gg(c, d, a, b, x[i+11], 14, 0x265e5a51);
b = gg(b, c, d, a, x[i+ 0], 20, 0xe9b6c7aa);
a = gg(a, b, c, d, x[i+ 5], 5 , 0xd62f105d);
d = gg(d, a, b, c, x[i+10], 9 , 0x2441453);
c = gg(c, d, a, b, x[i+15], 14, 0xd8a1e681);
b = gg(b, c, d, a, x[i+ 4], 20, 0xe7d3fbc8);
a = gg(a, b, c, d, x[i+ 9], 5 , 0x21e1cde6);
d = gg(d, a, b, c, x[i+14], 9 , 0xc33707d6);
c = gg(c, d, a, b, x[i+ 3], 14, 0xf4d50d87);
b = gg(b, c, d, a, x[i+ 8], 20, 0x455a14ed);
a = gg(a, b, c, d, x[i+13], 5 , 0xa9e3e905);
d = gg(d, a, b, c, x[i+ 2], 9 , 0xfcefa3f8);
c = gg(c, d, a, b, x[i+ 7], 14, 0x676f02d9);
b = gg(b, c, d, a, x[i+12], 20, 0x8d2a4c8a);
a = hh(a, b, c, d, x[i+ 5], 4 , 0xfffa3942);
d = hh(d, a, b, c, x[i+ 8], 11, 0x8771f681);
c = hh(c, d, a, b, x[i+11], 16, 0x6d9d6122);
b = hh(b, c, d, a, x[i+14], 23, 0xfde5380c);
a = hh(a, b, c, d, x[i+ 1], 4 , 0xa4beea44);
d = hh(d, a, b, c, x[i+ 4], 11, 0x4bdecfa9);
c = hh(c, d, a, b, x[i+ 7], 16, 0xf6bb4b60);
b = hh(b, c, d, a, x[i+10], 23, 0xbebfbc70);
a = hh(a, b, c, d, x[i+13], 4 , 0x289b7ec6);
d = hh(d, a, b, c, x[i+ 0], 11, 0xeaa127fa);
c = hh(c, d, a, b, x[i+ 3], 16, 0xd4ef3085);
b = hh(b, c, d, a, x[i+ 6], 23, 0x4881d05);
a = hh(a, b, c, d, x[i+ 9], 4 , 0xd9d4d039);
d = hh(d, a, b, c, x[i+12], 11, 0xe6db99e5);
c = hh(c, d, a, b, x[i+15], 16, 0x1fa27cf8);
b = hh(b, c, d, a, x[i+ 2], 23, 0xc4ac5665);
a = ii(a, b, c, d, x[i+ 0], 6 , 0xf4292244);
d = ii(d, a, b, c, x[i+ 7], 10, 0x432aff97);
c = ii(c, d, a, b, x[i+14], 15, 0xab9423a7);
b = ii(b, c, d, a, x[i+ 5], 21, 0xfc93a039);
a = ii(a, b, c, d, x[i+12], 6 , 0x655b59c3);
d = ii(d, a, b, c, x[i+ 3], 10, 0x8f0ccc92);
c = ii(c, d, a, b, x[i+10], 15, 0xffeff47d);
b = ii(b, c, d, a, x[i+ 1], 21, 0x85845dd1);
a = ii(a, b, c, d, x[i+ 8], 6 , 0x6fa87e4f);
d = ii(d, a, b, c, x[i+15], 10, 0xfe2ce6e0);
c = ii(c, d, a, b, x[i+ 6], 15, 0xa3014314);
b = ii(b, c, d, a, x[i+13], 21, 0x4e0811a1);
a = ii(a, b, c, d, x[i+ 4], 6 , 0xf7537e82);
d = ii(d, a, b, c, x[i+11], 10, 0xbd3af235);
c = ii(c, d, a, b, x[i+ 2], 15, 0x2ad7d2bb);
b = ii(b, c, d, a, x[i+ 9], 21, 0xeb86d391);
a += olda;
b += oldb;
c += oldc;
d += oldd;
}
return [ a, b, c, d ];
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
private function rol(num:uint, cnt:uint):uint
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* These functions implement the four basic operations the algorithm uses.
*/
private function cmn(q:uint, a:uint, b:uint, x:uint, s:uint, t:uint):uint {
return rol(a + q + x + t, s) + b;
}
private function ff(a:uint, b:uint, c:uint, d:uint, x:uint, s:uint, t:uint):uint {
return cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
private function gg(a:uint, b:uint, c:uint, d:uint, x:uint, s:uint, t:uint):uint {
return cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
private function hh(a:uint, b:uint, c:uint, d:uint, x:uint, s:uint, t:uint):uint {
return cmn(b ^ c ^ d, a, b, x, s, t);
}
private function ii(a:uint, b:uint, c:uint, d:uint, x:uint, s:uint, t:uint):uint {
return cmn(c ^ (b | (~d)), a, b, x, s, t);
}
public function toString():String {
return "md5";
}
}
}

View file

@ -1,106 +0,0 @@
/**
* SHA1
*
* An ActionScript 3 implementation of Secure Hash Algorithm, SHA-1, as defined
* in FIPS PUB 180-1
* Copyright (c) 2007 Henri Torgemane
*
* Derived from:
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
* in FIPS PUB 180-1
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
public class SHA1 extends SHABase implements IHash
{
public static const HASH_SIZE:int = 20;
public override function getHashSize():uint {
return HASH_SIZE;
}
protected override function core(x:Array, len:uint):Array
{
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w:Array = [];
var a:uint = 0x67452301; //1732584193;
var b:uint = 0xEFCDAB89; //-271733879;
var c:uint = 0x98BADCFE; //-1732584194;
var d:uint = 0x10325476; //271733878;
var e:uint = 0xC3D2E1F0; //-1009589776;
for(var i:uint = 0; i < x.length; i += 16)
{
var olda:uint = a;
var oldb:uint = b;
var oldc:uint = c;
var oldd:uint = d;
var olde:uint = e;
for(var j:uint = 0; j < 80; j++)
{
if (j < 16) {
w[j] = x[i + j] || 0;
} else {
w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
}
var t:uint = rol(a,5) + ft(j,b,c,d) + e + w[j] + kt(j);
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a += olda;
b += oldb;
c += oldc;
d += oldd;
e += olde;
}
return [ a, b, c, d, e ];
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
private function rol(num:uint, cnt:uint):uint
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
private function ft(t:uint, b:uint, c:uint, d:uint):uint
{
if(t < 20) return (b & c) | ((~b) & d);
if(t < 40) return b ^ c ^ d;
if(t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
private function kt(t:uint):uint
{
return (t < 20) ? 0x5A827999 : (t < 40) ? 0x6ED9EBA1 :
(t < 60) ? 0x8F1BBCDC : 0xCA62C1D6;
}
public override function toString():String {
return "sha1";
}
}
}

View file

@ -1,28 +0,0 @@
/**
* SHA224
*
* An ActionScript 3 implementation of Secure Hash Algorithm, SHA-224, as defined
* in FIPS PUB 180-2
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
public class SHA224 extends SHA256
{
function SHA224() {
h = [
0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
];
}
public override function getHashSize():uint {
return 28;
}
public override function toString():String {
return "sha224";
}
}
}

View file

@ -1,115 +0,0 @@
/**
* SHA256
*
* An ActionScript 3 implementation of Secure Hash Algorithm, SHA-256, as defined
* in FIPS PUB 180-2
* Copyright (c) 2007 Henri Torgemane
*
* Derived from:
* A JavaScript implementation of the Secure Hash Standard
* Version 0.3 Copyright Angel Marin 2003-2004 - http://anmar.eu.org/
* Derived from:
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
* in FIPS PUB 180-1
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
public class SHA256 extends SHABase implements IHash
{
protected static const k:Array = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2];
protected var h:Array = [
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
];
public function SHA256(){
}
public override function getHashSize():uint
{
return 32;
}
protected override function core(x:Array, len:uint):Array {
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w:Array = [];
var a:uint = h[0];
var b:uint = h[1];
var c:uint = h[2];
var d:uint = h[3];
var e:uint = h[4];
var f:uint = h[5];
var g:uint = h[6];
var h:uint = h[7];
for (var i:uint=0; i<x.length; i+=16) {
var olda:uint = a;
var oldb:uint = b;
var oldc:uint = c;
var oldd:uint = d;
var olde:uint = e;
var oldf:uint = f;
var oldg:uint = g;
var oldh:uint = h;
for (var j:uint=0; j<64; j++) {
if (j<16) {
w[j] = x[i+j] || 0;
} else {
var s0:uint = rrol(w[j-15],7)^rrol(w[j-15],18)^(w[j-15]>>>3);
var s1:uint = rrol(w[j-2], 17)^rrol(w[j-2],19)^(w[j-2]>>>10);
w[j] = w[j-16] + s0 + w[j-7] + s1;
}
var t2:uint = (rrol(a,2) ^ rrol(a,13) ^ rrol(a,22)) + ((a&b) ^ (a&c) ^ (b&c));
var t1:uint = h + (rrol(e,6) ^ rrol(e,11) ^ rrol(e,25)) + ((e&f)^(g&~e)) + k[j] + w[j]
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
a += olda;
b += oldb;
c += oldc;
d += oldd;
e += olde;
f += oldf;
g += oldg;
h += oldh;
}
return [ a,b,c,d,e,f,g,h ];
}
/*
* Bitwise rotate a 32-bit number to the right.
*/
protected function rrol(num:uint, cnt:uint):uint {
return (num << (32-cnt)) | (num >>> cnt);
}
public override function toString():String {
return "sha256";
}
}
}

View file

@ -1,71 +0,0 @@
/**
* SHABase
*
* An ActionScript 3 abstract class for the SHA family of hash functions
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.hash
{
import flash.utils.ByteArray;
import flash.utils.Endian;
public class SHABase implements IHash
{
public function SHABase() { }
public var pad_size:int = 40;
public function getInputSize():uint
{
return 64;
}
public function getHashSize():uint
{
return 0;
}
public function getPadSize():int
{
return pad_size;
}
public function hash(src:ByteArray):ByteArray
{
var savedLength:uint = src.length;
var savedEndian:String = src.endian;
src.endian = Endian.BIG_ENDIAN;
var len:uint = savedLength *8;
// pad to nearest int.
while (src.length%4!=0) {
src[src.length]=0;
}
// convert ByteArray to an array of uint
src.position=0;
var a:Array = [];
for (var i:uint=0;i<src.length;i+=4) {
a.push(src.readUnsignedInt());
}
var h:Array = core(a, len);
var out:ByteArray = new ByteArray;
var words:uint = getHashSize()/4;
for (i=0;i<words;i++) {
out.writeUnsignedInt(h[i]);
}
// unpad, to leave the source untouched.
src.length = savedLength;
src.endian = savedEndian;
return out;
}
protected function core(x:Array, len:uint):Array {
return null;
}
public function toString():String {
return "sha";
}
}
}

View file

@ -1,90 +0,0 @@
/**
* ARC4
*
* An ActionScript 3 implementation of RC4
* Copyright (c) 2007 Henri Torgemane
*
* Derived from:
* The jsbn library, Copyright (c) 2003-2005 Tom Wu
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.prng
{
import com.hurlant.crypto.symmetric.IStreamCipher;
import com.hurlant.util.Memory;
import flash.utils.ByteArray;
public class ARC4 implements IPRNG, IStreamCipher {
private var i:int = 0;
private var j:int = 0;
private var S:ByteArray;
private const psize:uint = 256;
public function ARC4(key:ByteArray = null){
S = new ByteArray;
if (key) {
init(key);
}
}
public function getPoolSize():uint {
return psize;
}
public function init(key:ByteArray):void {
var i:int;
var j:int;
var t:int;
for (i=0; i<256; ++i) {
S[i] = i;
}
j=0;
for (i=0; i<256; ++i) {
j = (j + S[i] + key[i%key.length]) & 255;
t = S[i];
S[i] = S[j];
S[j] = t;
}
this.i=0;
this.j=0;
}
public function next():uint {
var t:int;
i = (i+1)&255;
j = (j+S[i])&255;
t = S[i];
S[i] = S[j];
S[j] = t;
return S[(t+S[i])&255];
}
public function getBlockSize():uint {
return 1;
}
public function encrypt(block:ByteArray):void {
var i:uint = 0;
while (i<block.length) {
block[i++] ^= next();
}
}
public function decrypt(block:ByteArray):void {
encrypt(block); // the beauty of XOR.
}
public function dispose():void {
var i:uint = 0;
if (S!=null) {
for (i=0;i<S.length;i++) {
S[i] = Math.random()*256;
}
S.length=0;
S = null;
}
this.i = 0;
this.j = 0;
Memory.gc();
}
public function toString():String {
return "rc4";
}
}
}

View file

@ -1,20 +0,0 @@
/**
* IPRNG
*
* An interface for classes that can be used a pseudo-random number generators
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.prng
{
import flash.utils.ByteArray;
public interface IPRNG {
function getPoolSize():uint;
function init(key:ByteArray):void;
function next():uint;
function dispose():void;
function toString():String;
}
}

View file

@ -1,119 +0,0 @@
/**
* Random
*
* An ActionScript 3 implementation of a Random Number Generator
* Copyright (c) 2007 Henri Torgemane
*
* Derived from:
* The jsbn library, Copyright (c) 2003-2005 Tom Wu
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.prng
{
import flash.utils.ByteArray;
import com.hurlant.util.Memory;
import flash.system.System;
import flash.system.Capabilities;
import flash.accessibility.AccessibilityProperties;
import flash.display.SWFVersion;
import flash.display.Stage;
import flash.utils.getTimer;
import flash.text.Font;
public class Random
{
private var state:IPRNG;
private var ready:Boolean = false;
private var pool:ByteArray;
private var psize:int;
private var pptr:int;
private var seeded:Boolean = false;
public function Random(prng:Class = null) {
if (prng==null) prng = ARC4;
state = new prng as IPRNG;
psize= state.getPoolSize();
pool = new ByteArray;
pptr = 0;
while (pptr <psize) {
var t:uint = 65536*Math.random();
pool[pptr++] = t >>> 8;
pool[pptr++] = t&255;
}
pptr=0;
seed();
}
public function seed(x:int = 0):void {
if (x==0) {
x = new Date().getTime();
}
pool[pptr++] ^= x & 255;
pool[pptr++] ^= (x>>8)&255;
pool[pptr++] ^= (x>>16)&255;
pool[pptr++] ^= (x>>24)&255;
pptr %= psize;
seeded = true;
}
/**
* Gather anything we have that isn't entirely predictable:
* - memory used
* - system capabilities
* - timing stuff
* - installed fonts
*/
public function autoSeed():void {
var b:ByteArray = new ByteArray;
b.writeUnsignedInt(System.totalMemory);
b.writeUTF(Capabilities.serverString);
b.writeUnsignedInt(getTimer());
b.writeUnsignedInt((new Date).getTime());
var a:Array = Font.enumerateFonts(true);
for each (var f:Font in a) {
b.writeUTF(f.fontName);
b.writeUTF(f.fontStyle);
b.writeUTF(f.fontType);
}
b.position=0;
while (b.bytesAvailable>=4) {
seed(b.readUnsignedInt());
}
}
public function nextBytes(buffer:ByteArray, length:int):void {
while (length--) {
buffer.writeByte(nextByte());
}
}
public function nextByte():int {
if (!ready) {
if (!seeded) {
autoSeed();
}
state.init(pool);
pool.length = 0;
pptr = 0;
ready = true;
}
return state.next();
}
public function dispose():void {
for (var i:uint=0;i<pool.length;i++) {
pool[i] = Math.random()*256;
}
pool.length=0;
pool = null;
state.dispose();
state = null;
psize = 0;
pptr = 0;
Memory.gc();
}
public function toString():String {
return "random-"+state.toString();
}
}
}

View file

@ -1,142 +0,0 @@
/**
* TLSPRF
*
* An ActionScript 3 implementation of a pseudo-random generator
* that follows the TLS specification
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.prng
{
import flash.utils.ByteArray;
import com.hurlant.crypto.hash.HMAC;
import com.hurlant.crypto.hash.MD5;
import com.hurlant.crypto.hash.SHA1;
import com.hurlant.util.Memory;
import com.hurlant.util.Hex;
import flash.utils.IDataOutput;
/**
* There's "Random", and then there's TLS Random.
* .
* Still Pseudo-random, though.
*/
public class TLSPRF
{
// XXX WAY TOO MANY STRUCTURES HERE
// seed
private var seed:ByteArray;
// P_MD5's secret
private var s1:ByteArray;
// P_SHA-1's secret
private var s2:ByteArray;
// HMAC_MD5's A
private var a1:ByteArray;
// HMAC_SHA1's A
private var a2:ByteArray;
// Pool for P_MD5
private var p1:ByteArray;
// Pool for P_SHA1
private var p2:ByteArray;
// Data for HMAC_MD5
private var d1:ByteArray;
// Data for HMAC_SHA1
private var d2:ByteArray;
private var hmac_md5:HMAC;
private var hmac_sha1:HMAC;
public function TLSPRF(secret:ByteArray, label:String, seed:ByteArray) {
var l:int = Math.ceil(secret.length/2);
var s1:ByteArray = new ByteArray;
var s2:ByteArray = new ByteArray;
s1.writeBytes(secret, 0, l);
s2.writeBytes(secret, secret.length-l, l);
var s:ByteArray = new ByteArray;
s.writeUTFBytes(label);
s.writeBytes(seed);
this.seed = s;
this.s1 = s1;
this.s2 = s2;
hmac_md5 = new HMAC(new MD5);
hmac_sha1 = new HMAC(new SHA1);
this.a1 = hmac_md5.compute(s1, this.seed);
this.a2 = hmac_sha1.compute(s2, this.seed);
p1 = new ByteArray;
p2 = new ByteArray;
d1 = new ByteArray;
d2 = new ByteArray;
d1.position = MD5.HASH_SIZE;
d1.writeBytes(this.seed);
d2.position = SHA1.HASH_SIZE;
d2.writeBytes(this.seed);
}
// XXX HORRIBLY SLOW. REWRITE.
public function nextBytes(buffer:IDataOutput, length:int):void {
while (length--) {
buffer.writeByte(nextByte());
}
}
public function nextByte():int {
if (p1.bytesAvailable==0) {
more_md5();
}
if (p2.bytesAvailable==0) {
more_sha1();
}
return p1.readUnsignedByte()^p2.readUnsignedByte();
}
public function dispose():void {
seed = dba(seed);
s1 = dba(s1);
s2 = dba(s2);
a1 = dba(a1);
a2 = dba(a2);
p1 = dba(p1);
p2 = dba(p2);
d1 = dba(d1);
d2 = dba(d2);
hmac_md5.dispose();
hmac_md5 = null;
hmac_sha1.dispose();
hmac_sha1 = null;
Memory.gc();
}
public function toString():String {
return "tls-prf";
}
private function dba(ba:ByteArray):ByteArray {
for (var i:uint=0;i<ba.length;i++) {
ba[i]=0;
}
ba.length=0;
return null;
}
private function more_md5():void {
d1.position=0;
d1.writeBytes(a1);
var p:int = p1.position;
var more:ByteArray = hmac_md5.compute(s1, d1);
a1 = hmac_md5.compute(s1, a1);
p1.writeBytes(more);
p1.position=p;
}
private function more_sha1():void {
d2.position=0;
d2.writeBytes(a2);
var p:int = p2.position;
var more:ByteArray = hmac_sha1.compute(s2, d2);
a2 = hmac_sha1.compute(s2, a2);
p2.writeBytes(more);
p2.position=p;
}
}
}

View file

@ -1,339 +0,0 @@
/**
* RSAKey
*
* An ActionScript 3 implementation of RSA + PKCS#1 (light version)
* Copyright (c) 2007 Henri Torgemane
*
* Derived from:
* The jsbn library, Copyright (c) 2003-2005 Tom Wu
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.rsa
{
import com.hurlant.crypto.prng.Random;
import com.hurlant.math.BigInteger;
import com.hurlant.util.Memory;
import flash.utils.ByteArray;
import com.hurlant.crypto.hash.IHash;
import com.hurlant.util.Hex;
import com.hurlant.util.der.DER;
import com.hurlant.util.der.OID;
import com.hurlant.util.ArrayUtil;
import com.hurlant.util.der.Type;
import com.hurlant.util.der.Sequence;
import com.hurlant.util.der.ObjectIdentifier;
import com.hurlant.util.der.ByteString;
import com.hurlant.crypto.tls.TLSError;
/**
* Current limitations:
* exponent must be smaller than 2^31.
*/
public class RSAKey
{
// public key
public var e:int; // public exponent. must be <2^31
public var n:BigInteger; // modulus
// private key
public var d:BigInteger;
// extended private key
public var p:BigInteger;
public var q:BigInteger;
public var dmp1:BigInteger
public var dmq1:BigInteger;
public var coeff:BigInteger;
// flags. flags are cool.
protected var canDecrypt:Boolean;
protected var canEncrypt:Boolean;
public function RSAKey(N:BigInteger, E:int,
D:BigInteger=null,
P:BigInteger = null, Q:BigInteger=null,
DP:BigInteger=null, DQ:BigInteger=null,
C:BigInteger=null) {
this.n = N;
this.e = E;
this.d = D;
this.p = P;
this.q = Q;
this.dmp1 = DP;
this.dmq1 = DQ;
this.coeff = C;
// adjust a few flags.
canEncrypt = (n!=null&&e!=0);
canDecrypt = (canEncrypt&&d!=null);
}
public static function parsePublicKey(N:String, E:String):RSAKey {
return new RSAKey(new BigInteger(N, 16, true), parseInt(E,16));
}
public static function parsePrivateKey(N:String, E:String, D:String,
P:String=null,Q:String=null, DMP1:String=null, DMQ1:String=null, IQMP:String=null):RSAKey {
if (P==null) {
return new RSAKey(new BigInteger(N,16, true), parseInt(E,16), new BigInteger(D,16, true));
} else {
return new RSAKey(new BigInteger(N,16, true), parseInt(E,16), new BigInteger(D,16, true),
new BigInteger(P,16, true), new BigInteger(Q,16, true),
new BigInteger(DMP1,16, true), new BigInteger(DMQ1, 16, true),
new BigInteger(IQMP, 16, true));
}
}
public function getBlockSize():uint {
return (n.bitLength()+7)/8;
}
public function dispose():void {
e = 0;
n.dispose();
n = null;
Memory.gc();
}
public function encrypt(src:ByteArray, dst:ByteArray, length:uint, pad:Function=null):void {
_encrypt(doPublic, src, dst, length, pad, 0x02);
}
public function decrypt(src:ByteArray, dst:ByteArray, length:uint, pad:Function=null):void {
_decrypt(doPrivate2, src, dst, length, pad, 0x02);
}
public function sign(src:ByteArray, dst:ByteArray, length:uint, pad:Function = null):void {
_encrypt(doPrivate2, src, dst, length, pad, 0x01);
}
public function verify(src:ByteArray, dst:ByteArray, length:uint, pad:Function = null):void {
_decrypt(doPublic, src, dst, length, pad, 0x01);
}
private function _encrypt(op:Function, src:ByteArray, dst:ByteArray, length:uint, pad:Function, padType:int):void {
// adjust pad if needed
if (pad==null) pad = pkcs1pad;
// convert src to BigInteger
if (src.position >= src.length) {
src.position = 0;
}
var bl:uint = getBlockSize();
var end:int = src.position + length;
while (src.position<end) {
var block:BigInteger = new BigInteger(pad(src, end, bl, padType), bl, true);
var chunk:BigInteger = op(block);
chunk.toArray(dst);
}
}
private function _decrypt(op:Function, src:ByteArray, dst:ByteArray, length:uint, pad:Function, padType:int):void {
// adjust pad if needed
if (pad==null) pad = pkcs1unpad;
// convert src to BigInteger
if (src.position >= src.length) {
src.position = 0;
}
var bl:uint = getBlockSize();
var end:int = src.position + length;
while (src.position<end) {
var block:BigInteger = new BigInteger(src, bl, true);
var chunk:BigInteger = op(block);
var b:ByteArray = pad(chunk, bl, padType);
if (b == null)
throw new TLSError( "Decrypt error - padding function returned null!", TLSError.decode_error );
// if (b != null)
dst.writeBytes(b);
}
}
/**
* PKCS#1 pad. type 1 (0xff) or 2, random.
* puts as much data from src into it, leaves what doesn't fit alone.
*/
private function pkcs1pad(src:ByteArray, end:int, n:uint, type:uint = 0x02):ByteArray {
var out:ByteArray = new ByteArray;
var p:uint = src.position;
end = Math.min(end, src.length, p+n-11);
src.position = end;
var i:int = end-1;
while (i>=p && n>11) {
out[--n] = src[i--];
}
out[--n] = 0;
if (type==0x02) { // type 2
var rng:Random = new Random;
var x:int = 0;
while (n>2) {
do {
x = rng.nextByte();
} while (x==0);
out[--n] = x;
}
} else { // type 1
while (n>2) {
out[--n] = 0xFF;
}
}
out[--n] = type;
out[--n] = 0;
return out;
}
/**
*
* @param src
* @param n
* @param type Not used.
* @return
*
*/
private function pkcs1unpad(src:BigInteger, n:uint, type:uint = 0x02):ByteArray {
var b:ByteArray = src.toByteArray();
var out:ByteArray = new ByteArray;
b.position = 0;
var i:int = 0;
while (i<b.length && b[i]==0) ++i;
if (b.length-i != n-1 || b[i]!=type) {
trace("PKCS#1 unpad: i="+i+", expected b[i]=="+type+", got b[i]="+b[i].toString(16));
return null;
}
++i;
while (b[i]!=0) {
if (++i>=b.length) {
trace("PKCS#1 unpad: i="+i+", b[i-1]!=0 (="+b[i-1].toString(16)+")");
return null;
}
}
while (++i < b.length) {
out.writeByte(b[i]);
}
out.position = 0;
return out;
}
/**
* Raw pad.
*/
public function rawpad(src:ByteArray, end:int, n:uint, type:uint = 0):ByteArray {
return src;
}
public function rawunpad(src:BigInteger, n:uint, type:uint = 0):ByteArray {
return src.toByteArray();
}
public function toString():String {
return "rsa";
}
public function dump():String {
var s:String= "N="+n.toString(16)+"\n"+
"E="+e.toString(16)+"\n";
if (canDecrypt) {
s+="D="+d.toString(16)+"\n";
if (p!=null && q!=null) {
s+="P="+p.toString(16)+"\n";
s+="Q="+q.toString(16)+"\n";
s+="DMP1="+dmp1.toString(16)+"\n";
s+="DMQ1="+dmq1.toString(16)+"\n";
s+="IQMP="+coeff.toString(16)+"\n";
}
}
return s;
}
/**
*
* note: We should have a "nice" variant of this function that takes a callback,
* and perform the computation is small fragments, to keep the web browser
* usable.
*
* @param B
* @param E
* @return a new random private key B bits long, using public expt E
*
*/
public static function generate(B:uint, E:String):RSAKey {
var rng:Random = new Random;
var qs:uint = B>>1;
var key:RSAKey = new RSAKey(null,0,null);
key.e = parseInt(E, 16);
var ee:BigInteger = new BigInteger(E,16, true);
for (;;) {
for (;;) {
key.p = bigRandom(B-qs, rng);
if (key.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE)==0 &&
key.p.isProbablePrime(10)) break;
}
for (;;) {
key.q = bigRandom(qs, rng);
if (key.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE)==0 &&
key.q.isProbablePrime(10)) break;
}
if (key.p.compareTo(key.q)<=0) {
var t:BigInteger = key.p;
key.p = key.q;
key.q = t;
}
var p1:BigInteger = key.p.subtract(BigInteger.ONE);
var q1:BigInteger = key.q.subtract(BigInteger.ONE);
var phi:BigInteger = p1.multiply(q1);
if (phi.gcd(ee).compareTo(BigInteger.ONE)==0) {
key.n = key.p.multiply(key.q);
key.d = ee.modInverse(phi);
key.dmp1 = key.d.mod(p1);
key.dmq1 = key.d.mod(q1);
key.coeff = key.q.modInverse(key.p);
break;
}
}
return key;
}
protected static function bigRandom(bits:int, rnd:Random):BigInteger {
if (bits<2) return BigInteger.nbv(1);
var x:ByteArray = new ByteArray;
rnd.nextBytes(x, (bits>>3));
x.position = 0;
var b:BigInteger = new BigInteger(x,0,true);
b.primify(bits, 1);
return b;
}
protected function doPublic(x:BigInteger):BigInteger {
return x.modPowInt(e, n);
}
protected function doPrivate2(x:BigInteger):BigInteger {
if (p==null && q==null) {
return x.modPow(d,n);
}
var xp:BigInteger = x.mod(p).modPow(dmp1, p);
var xq:BigInteger = x.mod(q).modPow(dmq1, q);
while (xp.compareTo(xq)<0) {
xp = xp.add(p);
}
var r:BigInteger = xp.subtract(xq).multiply(coeff).mod(p).multiply(q).add(xq);
return r;
}
protected function doPrivate(x:BigInteger):BigInteger {
if (p==null || q==null) {
return x.modPow(d, n);
}
// TODO: re-calculate any missing CRT params
var xp:BigInteger = x.mod(p).modPow(dmp1, p);
var xq:BigInteger = x.mod(q).modPow(dmq1, q);
while (xp.compareTo(xq)<0) {
xp = xp.add(p);
}
return xp.subtract(xq).multiply(coeff).mod(p).multiply(q).add(xq);
}
}
}

View file

@ -1,375 +0,0 @@
/**
* BlowFishKey
*
* An Actionscript 3 implementation of the BlowFish encryption algorithm,
* as documented at http://www.schneier.com/blowfish.html
* Copyright (c) 2007 Henri Torgemane
*
* Derived from:
* The Bouncy Castle Crypto package,
* Copyright (c) 2000-2004 The Legion Of The Bouncy Castle
* (http://www.bouncycastle.org)
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
import com.hurlant.util.Memory;
public class BlowFishKey implements ISymmetricKey
{
private static const KP:Array = [ 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, 0xA4093822, 0x299F31D0,
0x082EFA98, 0xEC4E6C89, 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5,
0xB5470917, 0x9216D5D9, 0x8979FB1B ];
private static const KS0:Array = [ 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, 0x24A19947,
0xB3916CF7, 0x0801F2E2, 0x858EFC16, 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, 0x0D95748F, 0x728EB658,
0x718BCD58, 0x82154AEE, 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, 0xC5D1B023, 0x286085F0, 0xCA417918,
0xB8DB38EF, 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60,
0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, 0xA15486AF,
0x7C72E993, 0xB3EE1411, 0x636FBC2A, 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, 0xAFD6BA33, 0x6C24CF5C,
0x7A325381, 0x28958677, 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, 0x61D809CC, 0xFB21A991, 0x487CAC60,
0x5DEC8032, 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239,
0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0, 0x6A51A0D2,
0xD8542F68, 0x960FA728, 0xAB5133A3, 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, 0xA1F1651D, 0x39AF0176,
0x66CA593E, 0x82430E88, 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, 0xE06F75D8, 0x85C12073, 0x401A449F,
0x56C16AA6, 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B,
0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, 0xC1A94FB6,
0x409F60C4, 0x5E5C9EC2, 0x196A2463, 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, 0x6DFC511F, 0x9B30952C,
0xCC814544, 0xAF5EBD09, 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, 0xC0CBA857, 0x45C8740F, 0xD20B5F39,
0xB9D3FBDB, 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, 0x9E5C57BB,
0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, 0x695B27B0, 0xBBCA58C8,
0xE1FFA35D, 0xB8F011A0, 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, 0x9A53E479, 0xB6F84565, 0xD28E49BC,
0x4BFB9790, 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8, 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4,
0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, 0x8FF6E2FB,
0xF2122B64, 0x8888B812, 0x900DF01C, 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, 0x2F2F2218, 0xBE0E1777,
0xEA752DFE, 0x8B021FA1, 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81,
0xD2ADA8D9, 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF,
0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF, 0x2464369B,
0xF009B91E, 0x5563911D, 0x59DFA6AA, 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, 0x83260376, 0x6295CFA9,
0x11C81968, 0x4E734A41, 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915, 0xD60F573F, 0xBC9BC6E4, 0x2B60A476,
0x81E67400, 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A ];
private static const KS1:Array = [ 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, 0xECAA8C71,
0x699A17FF, 0x5664526C, 0xC2B19EE1, 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, 0x3F54989A, 0x5B429D65,
0x6B8FE4D6, 0x99F73FD6, 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, 0x4CDD2086, 0x8470EB26, 0x6382E9C6,
0x021ECC5E, 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1, 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737,
0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, 0xAE0CF51A,
0x3CB574B2, 0x25837A58, 0xDC0921BD, 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, 0x3AE5E581, 0x37C2DADC,
0xC8B57634, 0x9AF3DDA7, 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1,
0x183EB331, 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF,
0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, 0x7A584718,
0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, 0xEF1C1847, 0x3215D908,
0xDD433B37, 0x24C2BA16, 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, 0x71DFF89E, 0x10314E55, 0x81AC77D6,
0x5F11199B, 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E,
0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, 0x803E89D6,
0x5266C825, 0x2E4CC978, 0x9C10B36A, 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, 0xF2F74EA7, 0x361D2B3D,
0x1939260F, 0x19C27960, 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, 0xE3BC4595, 0xA67BC883, 0xB17F37D1,
0x018CFF28, 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84,
0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, 0xB5735C90,
0x4C70A239, 0xD59E9E0B, 0xCBAADE14, 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, 0x648B1EAF, 0x19BDF0CA,
0xA02369B9, 0x655ABB50, 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, 0x9B540B19, 0x875FA099, 0x95F7997E,
0x623D7DA8, 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281, 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99,
0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, 0x58EBF2EF,
0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, 0x45EEE2B6, 0xA3AAABEA,
0xDB6C4F15, 0xFACB4FD0, 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, 0xD81E799E, 0x86854DC7, 0xE44B476A,
0x3D816250, 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3, 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285,
0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, 0x3372F092,
0x8D937E41, 0xD65FECF1, 0x6C223BDB, 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, 0xA6078084, 0x19F8509E,
0xE8EFD855, 0x61D99735, 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC, 0x9E447A2E, 0xC3453484, 0xFDD56705,
0x0E1E9EC9, 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340, 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7 ];
private static const KS2:Array = [ 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, 0xD4082471,
0x3320F46A, 0x43B7D4B7, 0x500061AF, 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, 0x4D95FC1D, 0x96B591AF,
0x70F4DDD3, 0x66A02F45, 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, 0x96EB27B3, 0x55FD3941, 0xDA2547E6,
0xABCA0A9A, 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE,
0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, 0x20FE9E35,
0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, 0x3A6EFA74, 0xDD5B4332,
0x6841E7F7, 0xCA7820FB, 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, 0x55533A3A, 0x20838D87, 0xFE6BA9B7,
0xD096954B, 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C,
0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, 0x07F9C9EE,
0x41041F0F, 0x404779A4, 0x5D886E17, 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, 0x257B7834, 0x602A9C60,
0xDFF8E8A3, 0x1F636C1B, 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, 0x6B2395E0, 0x333E92E1, 0x3B240B62,
0xEEBEB922, 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0,
0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, 0xA812DC60,
0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, 0xF1290DC7, 0xCC00FFA3,
0xB5390F92, 0x690FED0B, 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, 0xBB132F88, 0x515BAD24, 0x7B9479BF,
0x763BD6EB, 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C,
0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, 0x44421659,
0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, 0x9DBC8057, 0xF0F7C086,
0x60787BF8, 0x6003604D, 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, 0x83426B33, 0xF01EAB71, 0xB0804187,
0x3C005E5F, 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2,
0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, 0x466E598E,
0x20B45770, 0x8CD55591, 0xC902DE4C, 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, 0xB77F19B6, 0xE0A9DC09,
0x662D09A1, 0xC4324633, 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F,
0x2868F169, 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027,
0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, 0x11E69ED7,
0x2338EA63, 0x53C2DD94, 0xC2C21634, 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, 0x6F05E409, 0x4B7C0188,
0x39720A3D, 0x7C927C24, 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC, 0xED545578, 0x08FCA5B5, 0xD83D7CD3,
0x4DAD0FC4, 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0 ];
private static const KS3:Array = [ 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, 0xD5118E9D,
0xBF0F7315, 0xD62D1C7E, 0xC700C47B, 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, 0x5748AB2F, 0xBC946E79,
0xC6A376D2, 0x6549C2C8, 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, 0x2939BBDB, 0xA9BA4650, 0xAC9526E8,
0xBE5EE304, 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22, 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4,
0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, 0xC72FEFD3,
0xF752F7DA, 0x3F046F69, 0x77FA0A59, 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, 0xE990FD5A, 0x9E34D797,
0x2CF0B7D9, 0x022B8B51, 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472,
0x5A88F54C, 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28,
0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD, 0xC3EB9E15,
0x3C9057A2, 0x97271AEC, 0xA93A072A, 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, 0x7533D928, 0xB155FDF5,
0x03563482, 0x8ABA3CBB, 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F, 0x4DE81751, 0x3830DC8E, 0x379D5862,
0x9320F991, 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680,
0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, 0x5BBEF7DD,
0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, 0x72EACEA8, 0xFA6484BB,
0x8D6612AE, 0xBF3C6F47, 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, 0x740E0D8D, 0xE75B1357, 0xF8721671,
0xAF537D5D, 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, 0xA08839E1,
0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, 0x1A908749, 0xD44FBD9A,
0xD0DADECB, 0xD50ADA38, 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF,
0x27D9459C, 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525, 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1,
0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, 0x9F1F9532,
0xE0D392DF, 0xD3A0342B, 0x8971F21E, 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, 0xDF359F8D, 0x9B992F2E,
0xE60B6F47, 0x0FE3F11D, 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F, 0x1618B166, 0xFD2C1D05, 0x848FD2C5,
0xF6FB2299, 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02, 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC,
0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, 0xC9AA53FD,
0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, 0x53113EC0, 0x1640E3D3,
0x38ABBD60, 0x2547ADF0, 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060, 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0,
0x4CF9AA7E, 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6 ];
// ====================================
// Useful constants
// ====================================
private static const ROUNDS:uint = 16;
private static const BLOCK_SIZE:uint = 8; // bytes = 64 bits
private static const SBOX_SK:uint = 256;
private static const P_SZ:uint = ROUNDS + 2;
private var S0:Array;
private var S1:Array;
private var S2:Array;
private var S3:Array; // the s-boxes
private var P:Array; // the p-array
private var key:ByteArray = null;
public function BlowFishKey(key:ByteArray) {
this.key = key;
setKey(key);
}
public function getBlockSize():uint
{
return BLOCK_SIZE;
}
public function decrypt(block:ByteArray, index:uint=0):void
{
decryptBlock(block, index, block, index);
}
public function dispose():void
{
var i:uint=0;
for (i=0;i<S0.length;i++) { S0[i]=0; }
for (i=0;i<S1.length;i++) { S1[i]=0; }
for (i=0;i<S2.length;i++) { S2[i]=0; }
for (i=0;i<S3.length;i++) { S3[i]=0; }
for (i=0;i<P.length;i++) { P[i]=0; }
S0 = null;
S1 = null;
S2 = null;
S3 = null;
P = null;
for (i=0;i<key.length;i++) {
key[i]=0;
}
key.length = 0;
key = null;
Memory.gc();
}
public function encrypt(block:ByteArray, index:uint=0):void
{
encryptBlock(block, index, block, index);
}
// ==================================
// Private Implementation
// ==================================
private function F(x:uint):uint
{
return (((S0[(x >>> 24)] + S1[(x >>> 16) & 0xff]) ^ S2[(x >>> 8) & 0xff]) + S3[x & 0xff]);
}
/**
* apply the encryption cycle to each value pair in the table.
*/
private function processTable(xl:uint, xr:uint, table:Array):void
{
var size:uint = table.length;
for (var s:uint = 0; s < size; s += 2)
{
xl ^= P[0];
for (var i:uint = 1; i < ROUNDS; i += 2)
{
xr ^= F(xl) ^ P[i];
xl ^= F(xr) ^ P[i + 1];
}
xr ^= P[ROUNDS + 1];
table[s] = xr;
table[s + 1] = xl;
xr = xl; // end of cycle swap
xl = table[s];
}
}
private function setKey(key:ByteArray):void
{
/*
* - comments are from _Applied Crypto_, Schneier, p338 please be
* careful comparing the two, AC numbers the arrays from 1, the enclosed
* code from 0.
*
* (1) Initialise the S-boxes and the P-array, with a fixed string This
* string contains the hexadecimal digits of pi (3.141...)
*/
S0 = KS0.concat();
S1 = KS1.concat();
S2 = KS2.concat();
S3 = KS3.concat();
P = KP.concat();
/*
* (2) Now, XOR P[0] with the first 32 bits of the key, XOR P[1] with
* the second 32-bits of the key, and so on for all bits of the key (up
* to P[17]). Repeatedly cycle through the key bits until the entire
* P-array has been XOR-ed with the key bits
*/
var keyLength:uint= key.length;
var keyIndex:uint = 0;
for (var i:uint = 0; i < P_SZ; i++)
{
// get the 32 bits of the key, in 4 * 8 bit chunks
var data:uint = 0x0000000;
for (var j:uint = 0; j < 4; j++)
{
// create a 32 bit block
data = (data << 8) | (key[keyIndex++] & 0xff);
// wrap when we get to the end of the key
if (keyIndex >= keyLength)
{
keyIndex = 0;
}
}
// XOR the newly created 32 bit chunk onto the P-array
P[i] ^= data;
}
/*
* (3) Encrypt the all-zero string with the Blowfish algorithm, using
* the subkeys described in (1) and (2)
*
* (4) Replace P1 and P2 with the output of step (3)
*
* (5) Encrypt the output of step(3) using the Blowfish algorithm, with
* the modified subkeys.
*
* (6) Replace P3 and P4 with the output of step (5)
*
* (7) Continue the process, replacing all elements of the P-array and
* then all four S-boxes in order, with the output of the continuously
* changing Blowfish algorithm
*/
processTable(0, 0, P);
processTable(P[P_SZ - 2], P[P_SZ - 1], S0);
processTable(S0[SBOX_SK - 2], S0[SBOX_SK - 1], S1);
processTable(S1[SBOX_SK - 2], S1[SBOX_SK - 1], S2);
processTable(S2[SBOX_SK - 2], S2[SBOX_SK - 1], S3);
}
/**
* Encrypt the given input starting at the given offset and place the result
* in the provided buffer starting at the given offset. The input will be an
* exact multiple of our blocksize.
*/
private function encryptBlock(src:ByteArray, srcIndex:uint, dst:ByteArray, dstIndex:uint):void
{
var xl:uint = BytesTo32bits(src, srcIndex);
var xr:uint = BytesTo32bits(src, srcIndex + 4);
xl ^= P[0];
for (var i:uint = 1; i < ROUNDS; i += 2)
{
xr ^= F(xl) ^ P[i];
xl ^= F(xr) ^ P[i + 1];
}
xr ^= P[ROUNDS + 1];
Bits32ToBytes(xr, dst, dstIndex);
Bits32ToBytes(xl, dst, dstIndex + 4);
}
/**
* Decrypt the given input starting at the given offset and place the result
* in the provided buffer starting at the given offset. The input will be an
* exact multiple of our blocksize.
*/
private function decryptBlock(src:ByteArray, srcIndex:uint, dst:ByteArray, dstIndex:uint):void
{
var xl:uint = BytesTo32bits(src, srcIndex);
var xr:uint = BytesTo32bits(src, srcIndex + 4);
xl ^= P[ROUNDS + 1];
for (var i:uint = ROUNDS; i > 0; i -= 2)
{
xr ^= F(xl) ^ P[i];
xl ^= F(xr) ^ P[i - 1];
}
xr ^= P[0];
Bits32ToBytes(xr, dst, dstIndex);
Bits32ToBytes(xl, dst, dstIndex + 4);
}
private function BytesTo32bits(b:ByteArray, i:uint):uint
{
return ((b[i] & 0xff) << 24) | ((b[i + 1] & 0xff) << 16) | ((b[i + 2] & 0xff) << 8) | ((b[i + 3] & 0xff));
}
private function Bits32ToBytes(i:uint, b:ByteArray, offset:uint):void
{
b[offset + 3] = i;
b[offset + 2] = (i >> 8);
b[offset + 1] = (i >> 16);
b[offset] = (i >> 24);
}
public function toString():String {
return "blowfish";
}
}
}

View file

@ -1,55 +0,0 @@
/**
* CBCMode
*
* An ActionScript 3 implementation of the CBC confidentiality mode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
/**
* CBC confidentiality mode. why not.
*/
public class CBCMode extends IVMode implements IMode
{
public function CBCMode(key:ISymmetricKey, padding:IPad = null) {
super(key, padding);
}
public function encrypt(src:ByteArray):void {
padding.pad(src);
var vector:ByteArray = getIV4e();
for (var i:uint=0;i<src.length;i+=blockSize) {
for (var j:uint=0;j<blockSize;j++) {
src[i+j] ^= vector[j];
}
key.encrypt(src, i);
vector.position=0;
vector.writeBytes(src, i, blockSize);
}
}
public function decrypt(src:ByteArray):void {
var vector:ByteArray = getIV4d();
var tmp:ByteArray = new ByteArray;
for (var i:uint=0;i<src.length;i+=blockSize) {
tmp.position=0;
tmp.writeBytes(src, i, blockSize);
key.decrypt(src, i);
for (var j:uint=0;j<blockSize;j++) {
src[i+j] ^= vector[j];
}
vector.position=0;
vector.writeBytes(tmp, 0, blockSize);
}
padding.unpad(src);
}
public function toString():String {
return key.toString()+"-cbc";
}
}
}

View file

@ -1,61 +0,0 @@
/**
* CFB8Mode
*
* An ActionScript 3 implementation of the CFB-8 confidentiality mode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import com.hurlant.crypto.tests.TestCase;
import flash.utils.ByteArray;
/**
*
* Note: The constructor accepts an optional padding argument, but ignores it otherwise.
*/
public class CFB8Mode extends IVMode implements IMode
{
public function CFB8Mode(key:ISymmetricKey, padding:IPad = null) {
super(key, null);
}
public function encrypt(src:ByteArray):void {
var vector:ByteArray = getIV4e();
var tmp:ByteArray = new ByteArray;
for (var i:uint=0;i<src.length;i++) {
tmp.position = 0;
tmp.writeBytes(vector);
key.encrypt(vector);
src[i] ^= vector[0];
// rotate
for (var j:uint=0;j<blockSize-1;j++) {
vector[j] = tmp[j+1];
}
vector[blockSize-1] = src[i];
}
}
public function decrypt(src:ByteArray):void {
var vector:ByteArray = getIV4d();
var tmp:ByteArray = new ByteArray;
for (var i:uint=0;i<src.length;i++) {
var c:uint = src[i];
tmp.position = 0;
tmp.writeBytes(vector); // I <- tmp
key.encrypt(vector); // O <- vector
src[i] ^= vector[0];
// rotate
for (var j:uint=0;j<blockSize-1;j++) {
vector[j] = tmp[j+1];
}
vector[blockSize-1] = c;
}
}
public function toString():String {
return key.toString()+"-cfb8";
}
}
}

View file

@ -1,64 +0,0 @@
/**
* CFBMode
*
* An ActionScript 3 implementation of the CFB confidentiality mode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
/**
* This is the "full" CFB.
* CFB1 and CFB8 are hiding somewhere else.
*
* Note: The constructor accepts an optional padding argument, but ignores it otherwise.
*/
public class CFBMode extends IVMode implements IMode
{
public function CFBMode(key:ISymmetricKey, padding:IPad = null) {
super(key,null);
}
public function encrypt(src:ByteArray):void
{
var l:uint = src.length;
var vector:ByteArray = getIV4e();
for (var i:uint=0;i<src.length;i+=blockSize) {
key.encrypt(vector);
var chunk:uint = (i+blockSize<l)?blockSize:l-i;
for (var j:uint=0;j<chunk;j++) {
src[i+j] ^= vector[j];
}
vector.position=0;
vector.writeBytes(src, i, chunk);
}
}
public function decrypt(src:ByteArray):void
{
var l:uint = src.length;
var vector:ByteArray = getIV4d();
var tmp:ByteArray = new ByteArray;
for (var i:uint=0;i<src.length;i+=blockSize) {
key.encrypt(vector);
var chunk:uint = (i+blockSize<l)?blockSize:l-i;
tmp.position=0;
tmp.writeBytes(src, i, chunk);
for (var j:uint=0;j<chunk;j++) {
src[i+j] ^= vector[j];
}
vector.position=0;
vector.writeBytes(tmp);
}
}
public function toString():String {
return key.toString()+"-cfb";
}
}
}

View file

@ -1,58 +0,0 @@
/**
* CTRMode
*
* An ActionScript 3 implementation of the counter confidentiality mode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
public class CTRMode extends IVMode implements IMode
{
public function CTRMode(key:ISymmetricKey, padding:IPad = null) {
super(key, padding);
}
public function encrypt(src:ByteArray):void
{
padding.pad(src);
var vector:ByteArray = getIV4e();
core(src, vector);
}
public function decrypt(src:ByteArray):void
{
var vector:ByteArray = getIV4d();
core(src, vector);
padding.unpad(src);
}
private function core(src:ByteArray, iv:ByteArray):void {
var X:ByteArray = new ByteArray;
var Xenc:ByteArray = new ByteArray;
X.writeBytes(iv);
for (var i:uint=0;i<src.length;i+=blockSize) {
Xenc.position=0;
Xenc.writeBytes(X);
key.encrypt(Xenc);
for (var j:uint=0;j<blockSize;j++) {
src[i+j] ^= Xenc[j];
}
for (j=blockSize-1;j>=0;--j) {
X[j]++;
if (X[j]!=0)
break;
}
}
}
public function toString():String {
return key.toString()+"-ctr";
}
}
}

View file

@ -1,365 +0,0 @@
/**
* DESKey
*
* An Actionscript 3 implementation of the Data Encryption Standard (DES)
* Copyright (c) 2007 Henri Torgemane
*
* Derived from:
* The Bouncy Castle Crypto package,
* Copyright (c) 2000-2004 The Legion Of The Bouncy Castle
* (http://www.bouncycastle.org)
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
import com.hurlant.util.Hex;
import com.hurlant.util.Memory;
public class DESKey implements ISymmetricKey
{
/**
* what follows is mainly taken from "Applied Cryptography", by Bruce
* Schneier, however it also bears great resemblance to Richard
* Outerbridge's D3DES...
*/
private static const Df_Key:Array = [ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32,
0x10, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67 ];
private static const bytebit:Array = [ 128, 64, 32, 16, 8, 4, 2, 1 ];
private static const bigbyte:Array = [ 0x800000, 0x400000, 0x200000, 0x100000, 0x80000, 0x40000, 0x20000, 0x10000, 0x8000,
0x4000, 0x2000, 0x1000, 0x800, 0x400, 0x200, 0x100, 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 ];
/*
* Use the key schedule specified in the Standard (ANSI X3.92-1981).
*/
private static const pc1:Array = [ 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2,
59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12,
4, 27, 19, 11, 3 ];
private static const totrot:Array = [ 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 ];
private static const pc2:Array = [ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40,
51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 ];
private static const SP1:Array = [ 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004,
0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004,
0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004,
0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404,
0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400,
0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404,
0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004,
0x00010400, 0x00000000, 0x01010004 ];
private static const SP2:Array = [ 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020,
0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020,
0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020,
0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020,
0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020,
0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020,
0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000,
0x80100020, 0x80108020, 0x00108000 ];
private static const SP3:Array = [ 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208,
0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208,
0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208,
0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000,
0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208,
0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208,
0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208,
0x00000008, 0x08020008, 0x00020200 ];
private static const SP4:Array = [ 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001,
0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001,
0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081,
0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001,
0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081,
0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000,
0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080,
0x00800000, 0x00002000, 0x00802080 ];
private static const SP5:Array = [ 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000,
0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000,
0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000,
0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100,
0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000,
0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100,
0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000,
0x40080000, 0x02080100, 0x40000100 ];
private static const SP6:Array = [ 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010,
0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010,
0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010,
0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010,
0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000,
0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010,
0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000,
0x20000000, 0x00400010, 0x20004010 ];
private static const SP7:Array = [ 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802,
0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802,
0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000,
0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800,
0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800,
0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000,
0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002,
0x04000800, 0x00000800, 0x00200002 ];
private static const SP8:Array = [ 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040,
0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040,
0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040,
0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000,
0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040,
0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040,
0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040,
0x00040040, 0x10000000, 0x10041000 ];
protected var key:ByteArray;
protected var encKey:Array;
protected var decKey:Array;
public function DESKey(key:ByteArray) {
this.key = key;
this.encKey = generateWorkingKey(true, key, 0);
this.decKey = generateWorkingKey(false, key, 0);
}
public function getBlockSize():uint
{
return 8;
}
public function decrypt(block:ByteArray, index:uint=0):void
{
desFunc(decKey, block, index, block, index);
}
public function dispose():void
{
var i:uint=0;
for (i=0;i<encKey.length;i++) { encKey[i]=0; }
for (i=0;i<decKey.length;i++) { decKey[i]=0; }
encKey=null;
decKey=null;
for (i=0;i<key.length;i++) { key[i]=0; }
key.length = 0;
key = null;
Memory.gc();
}
public function encrypt(block:ByteArray, index:uint=0):void
{
desFunc(encKey, block, index, block, index);
}
/**
* generate an integer based working key based on our secret key and what we
* processing we are planning to do.
*
* Acknowledgements for this routine go to James Gillogly & Phil Karn.
*/
protected function generateWorkingKey(encrypting:Boolean, key:ByteArray, off:uint):Array
{
//int[] newKey = new int[32];
var newKey:Array = [];
//boolean[] pc1m = new boolean[56], pcr = new boolean[56];
var pc1m:ByteArray = new ByteArray;
var pcr:ByteArray = new ByteArray;
var l:uint;
for (var j:uint = 0; j < 56; j++)
{
l = pc1[j];
pc1m[j] = ((key[off + (l >>> 3)] & bytebit[l & 07]) != 0);
}
for (var i:uint = 0; i < 16; i++)
{
var m:uint;
var n:uint;
if (encrypting)
{
m = i << 1;
}
else
{
m = (15 - i) << 1;
}
n = m + 1;
newKey[m] = newKey[n] = 0;
for (j = 0; j < 28; j++)
{
l = j + totrot[i];
if (l < 28)
{
pcr[j] = pc1m[l];
}
else
{
pcr[j] = pc1m[l - 28];
}
}
for (j = 28; j < 56; j++)
{
l = j + totrot[i];
if (l < 56)
{
pcr[j] = pc1m[l];
}
else
{
pcr[j] = pc1m[l - 28];
}
}
for (j = 0; j < 24; j++)
{
if (pcr[pc2[j]])
{
newKey[m] |= bigbyte[j];
}
if (pcr[pc2[j + 24]])
{
newKey[n] |= bigbyte[j];
}
}
}
//
// store the processed key
//
for (i = 0; i != 32; i += 2)
{
var i1:uint;
var i2:uint;
i1 = newKey[i];
i2 = newKey[i + 1];
newKey[i] = ((i1 & 0x00fc0000) << 6) | ((i1 & 0x00000fc0) << 10) | ((i2 & 0x00fc0000) >>> 10)
| ((i2 & 0x00000fc0) >>> 6);
newKey[i + 1] = ((i1 & 0x0003f000) << 12) | ((i1 & 0x0000003f) << 16) | ((i2 & 0x0003f000) >>> 4)
| (i2 & 0x0000003f);
}
return newKey;
}
/**
* the DES engine.
*/
protected function desFunc(wKey:Array, inp:ByteArray, inOff:uint, out:ByteArray, outOff:uint):void
{
var work:uint;
var right:uint;
var left:uint;
left = (inp[inOff + 0] & 0xff) << 24;
left |= (inp[inOff + 1] & 0xff) << 16;
left |= (inp[inOff + 2] & 0xff) << 8;
left |= (inp[inOff + 3] & 0xff);
right = (inp[inOff + 4] & 0xff) << 24;
right |= (inp[inOff + 5] & 0xff) << 16;
right |= (inp[inOff + 6] & 0xff) << 8;
right |= (inp[inOff + 7] & 0xff);
work = ((left >>> 4) ^ right) & 0x0f0f0f0f;
right ^= work;
left ^= (work << 4);
work = ((left >>> 16) ^ right) & 0x0000ffff;
right ^= work;
left ^= (work << 16);
work = ((right >>> 2) ^ left) & 0x33333333;
left ^= work;
right ^= (work << 2);
work = ((right >>> 8) ^ left) & 0x00ff00ff;
left ^= work;
right ^= (work << 8);
right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff;
work = (left ^ right) & 0xaaaaaaaa;
left ^= work;
right ^= work;
left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff;
for (var round:uint = 0; round < 8; round++)
{
var fval:uint;
work = (right << 28) | (right >>> 4);
work ^= wKey[round * 4 + 0];
fval = SP7[work & 0x3f];
fval |= SP5[(work >>> 8) & 0x3f];
fval |= SP3[(work >>> 16) & 0x3f];
fval |= SP1[(work >>> 24) & 0x3f];
work = right ^ wKey[round * 4 + 1];
fval |= SP8[work & 0x3f];
fval |= SP6[(work >>> 8) & 0x3f];
fval |= SP4[(work >>> 16) & 0x3f];
fval |= SP2[(work >>> 24) & 0x3f];
left ^= fval;
work = (left << 28) | (left >>> 4);
work ^= wKey[round * 4 + 2];
fval = SP7[work & 0x3f];
fval |= SP5[(work >>> 8) & 0x3f];
fval |= SP3[(work >>> 16) & 0x3f];
fval |= SP1[(work >>> 24) & 0x3f];
work = left ^ wKey[round * 4 + 3];
fval |= SP8[work & 0x3f];
fval |= SP6[(work >>> 8) & 0x3f];
fval |= SP4[(work >>> 16) & 0x3f];
fval |= SP2[(work >>> 24) & 0x3f];
right ^= fval;
}
right = (right << 31) | (right >>> 1);
work = (left ^ right) & 0xaaaaaaaa;
left ^= work;
right ^= work;
left = (left << 31) | (left >>> 1);
work = ((left >>> 8) ^ right) & 0x00ff00ff;
right ^= work;
left ^= (work << 8);
work = ((left >>> 2) ^ right) & 0x33333333;
right ^= work;
left ^= (work << 2);
work = ((right >>> 16) ^ left) & 0x0000ffff;
left ^= work;
right ^= (work << 16);
work = ((right >>> 4) ^ left) & 0x0f0f0f0f;
left ^= work;
right ^= (work << 4);
out[outOff + 0] = ((right >>> 24) & 0xff);
out[outOff + 1] = ((right >>> 16) & 0xff);
out[outOff + 2] = ((right >>> 8) & 0xff);
out[outOff + 3] = (right & 0xff);
out[outOff + 4] = ((left >>> 24) & 0xff);
out[outOff + 5] = ((left >>> 16) & 0xff);
out[outOff + 6] = ((left >>> 8) & 0xff);
out[outOff + 7] = (left & 0xff);
}
public function toString():String {
return "des";
}
}
}

View file

@ -1,86 +0,0 @@
/**
* ECBMode
*
* An ActionScript 3 implementation of the ECB confidentiality mode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
import com.hurlant.util.Memory;
import com.hurlant.util.Hex;
/**
* ECB mode.
* This uses a padding and a symmetric key.
* If no padding is given, PKCS#5 is used.
*/
public class ECBMode implements IMode, ICipher
{
private var key:ISymmetricKey;
private var padding:IPad;
public function ECBMode(key:ISymmetricKey, padding:IPad = null) {
this.key = key;
if (padding == null) {
padding = new PKCS5(key.getBlockSize());
} else {
padding.setBlockSize(key.getBlockSize());
}
this.padding = padding;
}
public function getBlockSize():uint {
return key.getBlockSize();
}
public function encrypt(src:ByteArray):void {
padding.pad(src);
src.position = 0;
var blockSize:uint = key.getBlockSize();
var tmp:ByteArray = new ByteArray;
var dst:ByteArray = new ByteArray;
for (var i:uint=0;i<src.length;i+=blockSize) {
tmp.length=0;
src.readBytes(tmp, 0, blockSize);
key.encrypt(tmp);
dst.writeBytes(tmp);
}
src.length=0;
src.writeBytes(dst);
}
public function decrypt(src:ByteArray):void {
src.position = 0;
var blockSize:uint = key.getBlockSize();
// sanity check.
if (src.length%blockSize!=0) {
throw new Error("ECB mode cipher length must be a multiple of blocksize "+blockSize);
}
var tmp:ByteArray = new ByteArray;
var dst:ByteArray = new ByteArray;
for (var i:uint=0;i<src.length;i+=blockSize) {
tmp.length=0;
src.readBytes(tmp, 0, blockSize);
key.decrypt(tmp);
dst.writeBytes(tmp);
}
padding.unpad(dst);
src.length=0;
src.writeBytes(dst);
}
public function dispose():void {
key.dispose();
key = null;
padding = null;
Memory.gc();
}
public function toString():String {
return key.toString()+"-ecb";
}
}
}

View file

@ -1,21 +0,0 @@
/**
* ICipher
*
* A generic interface to use symmetric ciphers
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
public interface ICipher
{
function getBlockSize():uint;
function encrypt(src:ByteArray):void;
function decrypt(src:ByteArray):void;
function dispose():void;
function toString():String;
}
}

View file

@ -1,15 +0,0 @@
/**
* IMode
*
* An interface for confidentiality modes to implement
* This could become deprecated at some point.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
public interface IMode extends ICipher
{
}
}

View file

@ -1,32 +0,0 @@
/**
* IPad
*
* An interface for padding mechanisms to implement.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
/**
* Tiny interface that represents a padding mechanism.
*/
public interface IPad
{
/**
* Add padding to the array
*/
function pad(a:ByteArray):void;
/**
* Remove padding from the array.
* @throws Error if the padding is invalid.
*/
function unpad(a:ByteArray):void;
/**
* Set the blockSize to work on
*/
function setBlockSize(bs:uint):void;
}
}

View file

@ -1,21 +0,0 @@
/**
* IStreamCipher
*
* A "marker" interface for stream ciphers.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric {
/**
* A marker to indicate how this cipher works.
* A stream cipher:
* - does not use initialization vector
* - keeps some internal state between calls to encrypt() and decrypt()
*
*/
public interface IStreamCipher extends ICipher {
}
}

View file

@ -1,35 +0,0 @@
/**
* ISymmetricKey
*
* An interface for symmetric encryption keys to implement.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
public interface ISymmetricKey
{
/**
* Returns the block size used by this particular encryption algorithm
*/
function getBlockSize():uint;
/**
* Encrypt one block of data in "block", starting at "index", of length "getBlockSize()"
*/
function encrypt(block:ByteArray, index:uint=0):void;
/**
* Decrypt one block of data in "block", starting at "index", of length "getBlockSize()"
*/
function decrypt(block:ByteArray, index:uint=0):void;
/**
* Attempts to destroy sensitive information from memory, such as encryption keys.
* Note: This is not guaranteed to work given the Flash sandbox model.
*/
function dispose():void;
function toString():String;
}
}

View file

@ -1,110 +0,0 @@
/**
* IVMode
*
* An abstract class for confidentialy modes that rely on an initialization vector.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import com.hurlant.crypto.prng.Random;
import com.hurlant.crypto.tests.TestCase;
import com.hurlant.util.Memory;
import flash.utils.ByteArray;
/**
* An "abtract" class to avoid redundant code in subclasses
*/
public class IVMode
{
protected var key:ISymmetricKey;
protected var padding:IPad;
// random generator used to generate IVs
protected var prng:Random;
// optional static IV. used for testing only.
protected var iv:ByteArray;
// generated IV is stored here.
protected var lastIV:ByteArray;
protected var blockSize:uint;
public function IVMode(key:ISymmetricKey, padding:IPad = null) {
this.key = key;
blockSize = key.getBlockSize();
if (padding == null) {
padding = new PKCS5(blockSize);
} else {
padding.setBlockSize(blockSize);
}
this.padding = padding;
prng = new Random;
iv = null;
lastIV = new ByteArray;
}
public function getBlockSize():uint {
return key.getBlockSize();
}
public function dispose():void {
var i:uint;
if (iv != null) {
for (i=0;i<iv.length;i++) {
iv[i] = prng.nextByte();
}
iv.length=0;
iv = null;
}
if (lastIV != null) {
for (i=0;i<iv.length;i++) {
lastIV[i] = prng.nextByte();
}
lastIV.length=0;
lastIV=null;
}
key.dispose();
key = null;
padding = null;
prng.dispose();
prng = null;
Memory.gc();
}
/**
* Optional function to force the IV value.
* Normally, an IV gets generated randomly at every encrypt() call.
* Also, use this to set the IV before calling decrypt()
* (if not set before decrypt(), the IV is read from the beginning of the stream.)
*/
public function set IV(value:ByteArray):void {
iv = value;
lastIV.length=0;
lastIV.writeBytes(iv);
}
public function get IV():ByteArray {
return lastIV;
}
protected function getIV4e():ByteArray {
var vec:ByteArray = new ByteArray;
if (iv) {
vec.writeBytes(iv);
} else {
prng.nextBytes(vec, blockSize);
}
lastIV.length=0;
lastIV.writeBytes(vec);
return vec;
}
protected function getIV4d():ByteArray {
var vec:ByteArray = new ByteArray;
if (iv) {
vec.writeBytes(iv);
} else {
throw new Error("an IV must be set before calling decrypt()");
}
return vec;
}
}
}

View file

@ -1,34 +0,0 @@
/**
* NullPad
*
* A padding class that doesn't pad.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
/**
* A pad that does nothing.
* Useful when you don't want padding in your Mode.
*/
public class NullPad implements IPad
{
public function unpad(a:ByteArray):void
{
return;
}
public function pad(a:ByteArray):void
{
return;
}
public function setBlockSize(bs:uint):void {
return;
}
}
}

View file

@ -1,52 +0,0 @@
/**
* OFBMode
*
* An ActionScript 3 implementation of the OFB confidentiality mode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
public class OFBMode extends IVMode implements IMode
{
public function OFBMode(key:ISymmetricKey, padding:IPad=null)
{
super(key, null);
}
public function encrypt(src:ByteArray):void
{
var vector:ByteArray = getIV4e();
core(src, vector);
}
public function decrypt(src:ByteArray):void
{
var vector:ByteArray = getIV4d();
core(src, vector);
}
private function core(src:ByteArray, iv:ByteArray):void {
var l:uint = src.length;
var tmp:ByteArray = new ByteArray;
for (var i:uint=0;i<src.length;i+=blockSize) {
key.encrypt(iv);
tmp.position=0;
tmp.writeBytes(iv);
var chunk:uint = (i+blockSize<l)?blockSize:l-i;
for (var j:uint=0;j<chunk;j++) {
src[i+j] ^= iv[j];
}
iv.position=0;
iv.writeBytes(tmp);
}
}
public function toString():String {
return key.toString()+"-ofb";
}
}
}

View file

@ -1,44 +0,0 @@
/**
* PKCS5
*
* A padding implementation of PKCS5.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
public class PKCS5 implements IPad
{
private var blockSize:uint;
public function PKCS5(blockSize:uint=0) {
this.blockSize = blockSize;
}
public function pad(a:ByteArray):void {
var c:uint = blockSize-a.length%blockSize;
for (var i:uint=0;i<c;i++){
a[a.length] = c;
}
}
public function unpad(a:ByteArray):void {
var c:uint = a.length%blockSize;
if (c!=0) throw new Error("PKCS#5::unpad: ByteArray.length isn't a multiple of the blockSize");
c = a[a.length-1];
for (var i:uint=c;i>0;i--) {
var v:uint = a[a.length-1];
a.length--;
if (c!=v) throw new Error("PKCS#5:unpad: Invalid padding value. expected ["+c+"], found ["+v+"]");
}
// that is all.
}
public function setBlockSize(bs:uint):void {
blockSize = bs;
}
}
}

View file

@ -1,44 +0,0 @@
/**
* TLSPad
*
* A padding implementation used by TLS
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric {
import flash.utils.ByteArray;
import com.hurlant.util.Hex;
import com.hurlant.crypto.tls.TLSError;
public class SSLPad implements IPad {
private var blockSize:uint;
public function SSLPad(blockSize:uint=0) {
this.blockSize = blockSize;
}
public function pad(a:ByteArray):void {
var c:uint = blockSize - (a.length+1)%blockSize;
for (var i:uint=0;i<=c;i++) {
a[a.length] = c;
}
}
public function unpad(a:ByteArray):void {
var c:uint = a.length%blockSize;
if (c!=0) throw new TLSError("SSLPad::unpad: ByteArray.length isn't a multiple of the blockSize", TLSError.bad_record_mac);
c = a[a.length-1];
for (var i:uint=c;i>0;i--) {
var v:uint = a[a.length-1];
a.length--;
// But LOOK! SSL 3.0 doesn't care about this, bytes are arbitrary!
// if (c!=v) throw new TLSError("SSLPad:unpad: Invalid padding value. expected ["+c+"], found ["+v+"]", TLSError.bad_record_mac);
}
a.length--;
}
public function setBlockSize(bs:uint):void {
blockSize = bs;
}
}
}

View file

@ -1,60 +0,0 @@
/**
* SimpleIVMode
*
* A convenience class that automatically places the IV
* at the beginning of the encrypted stream, so it doesn't have to
* be handled explicitely.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
import com.hurlant.util.Memory;
public class SimpleIVMode implements IMode, ICipher
{
protected var mode:IVMode;
protected var cipher:ICipher;
public function SimpleIVMode(mode:IVMode) {
this.mode = mode;
cipher = mode as ICipher;
}
public function getBlockSize():uint {
return mode.getBlockSize();
}
public function dispose():void {
mode.dispose();
mode = null;
cipher = null;
Memory.gc();
}
public function encrypt(src:ByteArray):void {
cipher.encrypt(src);
var tmp:ByteArray = new ByteArray;
tmp.writeBytes(mode.IV);
tmp.writeBytes(src);
src.position=0;
src.writeBytes(tmp);
}
public function decrypt(src:ByteArray):void {
var tmp:ByteArray = new ByteArray;
tmp.writeBytes(src, 0, getBlockSize());
mode.IV = tmp;
tmp = new ByteArray;
tmp.writeBytes(src, getBlockSize());
cipher.decrypt(tmp);
src.length=0;
src.writeBytes(tmp);
}
public function toString():String {
return "simple-"+cipher.toString();
}
}
}

View file

@ -1,42 +0,0 @@
/**
* TLSPad
*
* A padding implementation used by TLS
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric {
import flash.utils.ByteArray;
import com.hurlant.util.Hex;
import com.hurlant.crypto.tls.TLSError;
public class TLSPad implements IPad {
private var blockSize:uint;
public function TLSPad(blockSize:uint=0) {
this.blockSize = blockSize;
}
public function pad(a:ByteArray):void {
var c:uint = blockSize - (a.length+1)%blockSize;
for (var i:uint=0;i<=c;i++) {
a[a.length] = c;
}
}
public function unpad(a:ByteArray):void {
var c:uint = a.length%blockSize;
if (c!=0) throw new TLSError("TLSPad::unpad: ByteArray.length isn't a multiple of the blockSize", TLSError.bad_record_mac);
c = a[a.length-1];
for (var i:uint=c;i>0;i--) {
var v:uint = a[a.length-1];
a.length--;
if (c!=v) throw new TLSError("TLSPad:unpad: Invalid padding value. expected ["+c+"], found ["+v+"]", TLSError.bad_record_mac);
}
a.length--;
// mostly ripped off from PKCS5.as, but with subtle differences
}
public function setBlockSize(bs:uint):void {
blockSize = bs;
}
}
}

View file

@ -1,88 +0,0 @@
/**
* TripleDESKey
*
* An Actionscript 3 implementation of Triple DES
* Copyright (c) 2007 Henri Torgemane
*
* Derived from:
* The Bouncy Castle Crypto package,
* Copyright (c) 2000-2004 The Legion Of The Bouncy Castle
* (http://www.bouncycastle.org)
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import flash.utils.ByteArray;
import com.hurlant.util.Memory;
import com.hurlant.util.Hex;
public class TripleDESKey extends DESKey
{
protected var encKey2:Array;
protected var encKey3:Array;
protected var decKey2:Array;
protected var decKey3:Array;
/**
* This supports 2TDES and 3TDES.
* If the key passed is 128 bits, 2TDES is used.
* If the key has 192 bits, 3TDES is used.
* Other key lengths give "undefined" results.
*/
public function TripleDESKey(key:ByteArray)
{
super(key);
encKey2 = generateWorkingKey(false, key, 8);
decKey2 = generateWorkingKey(true, key, 8);
if (key.length>16) {
encKey3 = generateWorkingKey(true, key, 16);
decKey3 = generateWorkingKey(false, key, 16);
} else {
encKey3 = encKey;
decKey3 = decKey;
}
}
public override function dispose():void
{
super.dispose();
var i:uint = 0;
if (encKey2!=null) {
for (i=0;i<encKey2.length;i++) { encKey2[i]=0; }
encKey2=null;
}
if (encKey3!=null) {
for (i=0;i<encKey3.length;i++) { encKey3[i]=0; }
encKey3=null;
}
if (decKey2!=null) {
for (i=0;i<decKey2.length;i++) { decKey2[i]=0; }
decKey2=null
}
if (decKey3!=null) {
for (i=0;i<decKey3.length;i++) { decKey3[i]=0; }
decKey3=null;
}
Memory.gc();
}
public override function encrypt(block:ByteArray, index:uint=0):void
{
desFunc(encKey, block,index, block,index);
desFunc(encKey2, block,index, block,index);
desFunc(encKey3, block,index, block,index);
}
public override function decrypt(block:ByteArray, index:uint=0):void
{
desFunc(decKey3, block, index, block, index);
desFunc(decKey2, block, index, block, index);
desFunc(decKey, block, index, block, index);
}
public override function toString():String {
return "3des";
}
}
}

View file

@ -1,94 +0,0 @@
/**
* XTeaKey
*
* An ActionScript 3 implementation of the XTea algorithm
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.symmetric
{
import com.hurlant.crypto.prng.Random;
import com.hurlant.util.Memory;
import flash.utils.ByteArray;
public class XTeaKey implements ISymmetricKey
{
public const NUM_ROUNDS:uint = 64;
private var k:Array;
public function XTeaKey(a:ByteArray) {
a.position=0;
k = [a.readUnsignedInt(),a.readUnsignedInt(),a.readUnsignedInt(),a.readUnsignedInt()];
}
/**
* K is an hex string with 32 digits.
*/
public static function parseKey(K:String):XTeaKey {
var a:ByteArray = new ByteArray;
a.writeUnsignedInt(parseInt(K.substr(0,8),16));
a.writeUnsignedInt(parseInt(K.substr(8,8),16));
a.writeUnsignedInt(parseInt(K.substr(16,8),16));
a.writeUnsignedInt(parseInt(K.substr(24,8),16));
a.position = 0;
return new XTeaKey(a);
}
public function getBlockSize():uint {
return 8;
}
public function encrypt(block:ByteArray, index:uint=0):void {
block.position = index;
var v0:uint = block.readUnsignedInt();
var v1:uint = block.readUnsignedInt();
var i:uint;
var sum:uint =0;
var delta:uint = 0x9E3779B9;
for (i=0; i<NUM_ROUNDS; i++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
}
block.position-=8;
block.writeUnsignedInt(v0);
block.writeUnsignedInt(v1);
}
public function decrypt(block:ByteArray, index:uint=0):void {
block.position = index;
var v0:uint = block.readUnsignedInt();
var v1:uint = block.readUnsignedInt();
var i:uint;
var delta:uint = 0x9E3779B9;
var sum:uint = delta*NUM_ROUNDS;
for (i=0; i<NUM_ROUNDS; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
}
block.position-=8;
block.writeUnsignedInt(v0);
block.writeUnsignedInt(v1);
}
public function dispose():void {
//private var k:Array;
var r:Random = new Random;
for (var i:uint=0;i<k.length;i++) {
k[i] = r.nextByte();
delete k[i];
}
k = null;
Memory.gc();
}
public function toString():String {
return "xtea";
}
}
}

View file

@ -1,29 +0,0 @@
#!/usr/bin/perl
use strict;
use warnings;
sub say {
my $w = shift;
print $w;
print "\n";
}
sub dump {
my $i = shift;
&say(sprintf("Sbox[%d] = _Sbox[%d]", $i, $i));
&say(sprintf("InvSbox[%d] = _InvSbox[%d]", $i, $i));
&say(sprintf("Xtime2Sbox[%d] = _Xtime2Sbox[%d]", $i, $i));
&say(sprintf("Xtime3Sbox[%d] = _Xtime3Sbox[%d]", $i, $i));
&say(sprintf("Xtime2[%d] = _Xtime2[%d]", $i, $i));
&say(sprintf("Xtime9[%d] = _Xtime9[%d]", $i, $i));
&say(sprintf("XtimeB[%d] = _XtimeB[%d]", $i, $i));
&say(sprintf("XtimeD[%d] = _XtimeD[%d]", $i, $i));
&say(sprintf("XtimeE[%d] = _XtimeE[%d]", $i, $i));
}
for (my $i=0;$i<256;$i++) {
&dump($i);
}

View file

@ -1,58 +0,0 @@
/**
* ARC4Test
*
* A test class for ARC4
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import com.hurlant.util.Hex;
import flash.utils.ByteArray;
import com.hurlant.crypto.prng.ARC4;
public class ARC4Test extends TestCase
{
public function ARC4Test(h:ITestHarness)
{
super(h, "ARC4 Test");
runTest(testLameVectors,"ARC4 Test Vectors");
h.endTestCase();
}
/**
* Sad test vectors pilfered from
* http://en.wikipedia.org/wiki/RC4
*/
public function testLameVectors():void {
var keys:Array = [
Hex.fromString("Key"),
Hex.fromString("Wiki"),
Hex.fromString("Secret")];
var pts:Array = [
Hex.fromString("Plaintext"),
Hex.fromString("pedia"),
Hex.fromString("Attack at dawn")];
var cts:Array = [
"BBF316E8D940AF0AD3",
"1021BF0420",
"45A01F645FC35B383552544B9BF5"];
for (var i:uint=0;i<keys.length;i++) {
var key:ByteArray = Hex.toArray(keys[i]);
var pt:ByteArray = Hex.toArray(pts[i]);
var rc4:ARC4 = new ARC4(key);
rc4.encrypt(pt);
var out:String = Hex.fromArray(pt).toUpperCase();
assert("comparing "+cts[i]+" to "+out, cts[i]==out);
// now go back to plaintext
rc4.init(key);
rc4.decrypt(pt);
out = Hex.fromArray(pt);
assert("comparing "+pts[i]+" to "+out, pts[i]==out);
}
}
}
}

View file

@ -1,39 +0,0 @@
/**
* BigIntegerTest
*
* A test class for BigInteger
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import com.hurlant.math.BigInteger;
import com.hurlant.util.Hex;
public class BigIntegerTest extends TestCase
{
public function BigIntegerTest(h:ITestHarness)
{
super(h, "BigInteger Tests");
runTest(testAdd, "BigInteger Addition");
h.endTestCase();
}
public function testAdd():void {
var n1:BigInteger = BigInteger.nbv(25);
var n2:BigInteger = BigInteger.nbv(1002);
var n3:BigInteger = n1.add(n2);
var v:int = n3.valueOf();
assert("25+1002 = "+v, 25+1002==v);
var p:BigInteger = new BigInteger(Hex.toArray("e564d8b801a61f47"));
var xp:BigInteger = new BigInteger(Hex.toArray("99246db2a3507fa"));
xp = xp.add(p);
assert("xp==eef71f932bdb2741", xp.toString(16)=="eef71f932bdb2741");
}
}
}

View file

@ -1,148 +0,0 @@
/**
* BlowFishKeyTest
*
* A test class for BlowFishKey
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import com.hurlant.crypto.symmetric.BlowFishKey;
import com.hurlant.util.Hex;
import flash.utils.ByteArray;
public class BlowFishKeyTest extends TestCase
{
public function BlowFishKeyTest(h:ITestHarness)
{
super(h, "BlowFishKey Test");
runTest(testECB,"BlowFish ECB Test Vectors");
h.endTestCase();
}
/**
* Test vectors from http://www.schneier.com/code/vectors.txt
*/
public function testECB():void {
var keys:Array = [
"0000000000000000",
"FFFFFFFFFFFFFFFF",
"3000000000000000",
"1111111111111111",
"0123456789ABCDEF",
"1111111111111111",
"0000000000000000",
"FEDCBA9876543210",
"7CA110454A1A6E57",
"0131D9619DC1376E",
"07A1133E4A0B2686",
"3849674C2602319E",
"04B915BA43FEB5B6",
"0113B970FD34F2CE",
"0170F175468FB5E6",
"43297FAD38E373FE",
"07A7137045DA2A16",
"04689104C2FD3B2F",
"37D06BB516CB7546",
"1F08260D1AC2465E",
"584023641ABA6176",
"025816164629B007",
"49793EBC79B3258F",
"4FB05E1515AB73A7",
"49E95D6D4CA229BF",
"018310DC409B26D6",
"1C587F1C13924FEF",
"0101010101010101",
"1F1F1F1F0E0E0E0E",
"E0FEE0FEF1FEF1FE",
"0000000000000000",
"FFFFFFFFFFFFFFFF",
"0123456789ABCDEF",
"FEDCBA9876543210" ];
var pts:Array = [
"0000000000000000",
"FFFFFFFFFFFFFFFF",
"1000000000000001",
"1111111111111111",
"1111111111111111",
"0123456789ABCDEF",
"0000000000000000",
"0123456789ABCDEF",
"01A1D6D039776742",
"5CD54CA83DEF57DA",
"0248D43806F67172",
"51454B582DDF440A",
"42FD443059577FA2",
"059B5E0851CF143A",
"0756D8E0774761D2",
"762514B829BF486A",
"3BDD119049372802",
"26955F6835AF609A",
"164D5E404F275232",
"6B056E18759F5CCA",
"004BD6EF09176062",
"480D39006EE762F2",
"437540C8698F3CFA",
"072D43A077075292",
"02FE55778117F12A",
"1D9D5C5018F728C2",
"305532286D6F295A",
"0123456789ABCDEF",
"0123456789ABCDEF",
"0123456789ABCDEF",
"FFFFFFFFFFFFFFFF",
"0000000000000000",
"0000000000000000",
"FFFFFFFFFFFFFFFF" ];
var cts:Array = [
"4EF997456198DD78",
"51866FD5B85ECB8A",
"7D856F9A613063F2",
"2466DD878B963C9D",
"61F9C3802281B096",
"7D0CC630AFDA1EC7",
"4EF997456198DD78",
"0ACEAB0FC6A0A28D",
"59C68245EB05282B",
"B1B8CC0B250F09A0",
"1730E5778BEA1DA4",
"A25E7856CF2651EB",
"353882B109CE8F1A",
"48F4D0884C379918",
"432193B78951FC98",
"13F04154D69D1AE5",
"2EEDDA93FFD39C79",
"D887E0393C2DA6E3",
"5F99D04F5B163969",
"4A057A3B24D3977B",
"452031C1E4FADA8E",
"7555AE39F59B87BD",
"53C55F9CB49FC019",
"7A8E7BFA937E89A3",
"CF9C5D7A4986ADB5",
"D1ABB290658BC778",
"55CB3774D13EF201",
"FA34EC4847B268B2",
"A790795108EA3CAE",
"C39E072D9FAC631D",
"014933E0CDAFF6E4",
"F21E9A77B71C49BC",
"245946885754369A",
"6B5C5A9C5D9E0A5A" ];
for (var i:uint=0;i<keys.length;i++) {
var key:ByteArray = Hex.toArray(keys[i]);
var pt:ByteArray = Hex.toArray(pts[i]);
var bf:BlowFishKey = new BlowFishKey(key);
bf.encrypt(pt);
var out:String = Hex.fromArray(pt).toUpperCase();
assert("comparing "+cts[i]+" to "+out, cts[i]==out);
// now go back to plaintext
bf.decrypt(pt);
out = Hex.fromArray(pt).toUpperCase();
assert("comparing "+pts[i]+" to "+out, pts[i]==out);
}
}
}
}

View file

@ -1,160 +0,0 @@
/**
* CBCModeTest
*
* A test class for CBCMode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import com.hurlant.crypto.symmetric.AESKey;
import com.hurlant.crypto.symmetric.CBCMode;
import com.hurlant.crypto.symmetric.NullPad;
import com.hurlant.crypto.symmetric.XTeaKey;
import com.hurlant.util.Hex;
import flash.utils.ByteArray;
public class CBCModeTest extends TestCase
{
public function CBCModeTest(h:ITestHarness) {
super(h, "CBCMode Test");
runTest(testAES,"CBC AES Test Vectors");
runTest(testXTea,"CBC XTea Test Vectors");
//
runTest(testCBC_AES128, "CBC AES-128 Test Vectors");
runTest(testCBC_AES192, "CBC AES-192 Test Vectors");
runTest(testCBC_AES256, "CBC AES-256 Test Vectors");
h.endTestCase();
}
/**
* Hawt NIST Vectors: http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
* Section F.2.1 and below.
*/
public function testCBC_AES128():void {
var key:ByteArray = Hex.toArray("2b7e151628aed2a6abf7158809cf4f3c");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"7649abac8119b246cee98e9b12e9197d" +
"5086cb9b507219ee95db113a917678b2" +
"73bed6b8e3c1743b7116e69e22229516" +
"3ff1caa1681fac09120eca307586e1a7");
var cbc:CBCMode = new CBCMode(new AESKey(key), new NullPad);
cbc.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
cbc.encrypt(src);
assert("CBC_AES128 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
cbc.decrypt(src);
assert("CBC_AES128 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
public function testCBC_AES192():void {
var key:ByteArray = Hex.toArray("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"4f021db243bc633d7178183a9fa071e8" +
"b4d9ada9ad7dedf4e5e738763f69145a" +
"571b242012fb7ae07fa9baac3df102e0" +
"08b0e27988598881d920a9e64f5615cd");
var cbc:CBCMode = new CBCMode(new AESKey(key), new NullPad);
cbc.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
cbc.encrypt(src);
assert("CBC_AES192 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
cbc.decrypt(src);
assert("CBC_AES192 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
public function testCBC_AES256():void {
var key:ByteArray = Hex.toArray(
"603deb1015ca71be2b73aef0857d7781" +
"1f352c073b6108d72d9810a30914dff4");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"f58c4c04d6e5f1ba779eabfb5f7bfbd6" +
"9cfc4e967edb808d679f777bc6702c7d" +
"39f23369a9d9bacfa530e26304231461" +
"b2eb05e2c39be9fcda6c19078c6a9d1b");
var cbc:CBCMode = new CBCMode(new AESKey(key), new NullPad);
cbc.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
cbc.encrypt(src);
assert("CBC_AES256 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
cbc.decrypt(src);
assert("CBC_AES256 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
/**
* For now the main goal is to show we can decrypt what we encrypt in this mode.
* Eventually, this should get correlated with some well known vectors.
*/
public function testAES():void {
var keys:Array = [
"00010203050607080A0B0C0D0F101112",
"14151617191A1B1C1E1F202123242526"];
var cts:Array = [
"D8F532538289EF7D06B506A4FD5BE9C94894C5508A8D8E29AB600DB0261F0555A8FA287B89E65C0973F1F8283E70C72863FE1C8F1F782084CE05626E961A67B3",
"59AB30F4D4EE6E4FF9907EF65B1FB68C96890CE217689B1BE0C93ED51CF21BB5A0101A8C30714EC4F52DBC9C6F4126067D363F67ABE58463005E679B68F0B496"];
var pts:Array = [
"506812A45F08C889B97F5980038B8359506812A45F08C889B97F5980038B8359506812A45F08C889B97F5980038B8359",
"5C6D71CA30DE8B8B00549984D2EC7D4B5C6D71CA30DE8B8B00549984D2EC7D4B5C6D71CA30DE8B8B00549984D2EC7D4B"];
for (var i:uint=0;i<keys.length;i++) {
var key:ByteArray = Hex.toArray(keys[i]);
var pt:ByteArray = Hex.toArray(pts[i]);
var aes:AESKey = new AESKey(key);
var cbc:CBCMode = new CBCMode(aes);
cbc.IV = Hex.toArray("00000000000000000000000000000000");
cbc.encrypt(pt);
var str:String = Hex.fromArray(pt).toUpperCase();
assert("comparing "+cts[i]+" to "+str, cts[i]==str);
// back to pt
cbc.decrypt(pt);
str = Hex.fromArray(pt).toUpperCase();
assert("comparing "+pts[i]+" to "+str, pts[i]==str);
}
}
public function testXTea():void {
var keys:Array=[
"00000000000000000000000000000000",
"2b02056806144976775d0e266c287843"];
var cts:Array = [
"2dc7e8d3695b0538d8f1640d46dca717790af2ab545e11f3b08e798eb3f17b1744299d4d20b534aa",
"790958213819878370eb8251ffdac371081c5a457fc42502c63910306fea150be8674c3b8e675516"];
var pts:Array=[
"0000000000000000000000000000000000000000000000000000000000000000",
"74657374206d652e74657374206d652e74657374206d652e74657374206d652e"];
for (var i:uint=0;i<keys.length;i++) {
var key:ByteArray = Hex.toArray(keys[i]);
var pt:ByteArray = Hex.toArray(pts[i]);
var tea:XTeaKey = new XTeaKey(key);
var cbc:CBCMode = new CBCMode(tea);
cbc.IV = Hex.toArray("0000000000000000");
cbc.encrypt(pt);
var str:String = Hex.fromArray(pt);
assert("comparing "+cts[i]+" to "+str, cts[i]==str);
// now go back to plaintext.
cbc.decrypt(pt);
str = Hex.fromArray(pt);
assert("comparing "+pts[i]+" to "+str, pts[i]==str);
}
}
}
}

View file

@ -1,71 +0,0 @@
/**
* CFB8ModeTest
*
* A test class for CFB8Mode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import flash.utils.ByteArray;
import com.hurlant.util.Hex;
import com.hurlant.crypto.symmetric.CFB8Mode;
import com.hurlant.crypto.symmetric.AESKey;
import com.hurlant.crypto.symmetric.NullPad;
public class CFB8ModeTest extends TestCase
{
public function CFB8ModeTest(h:ITestHarness) {
super(h,"CBF8Mode Test");
runTest(testCFB8_AES128, "CFB-8 AES-128 Test Vectors");
runTest(testCFB8_AES192, "CFB-8 AES-192 Test Vectors");
runTest(testCFB8_AES256, "CFB-8 AES-192 Test Vectors");
h.endTestCase();
}
/**
* http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
*/
public function testCFB8_AES128():void {
var key:ByteArray = Hex.toArray("2b7e151628aed2a6abf7158809cf4f3c");
var pt:ByteArray = Hex.toArray("6bc1bee22e409f96e93d7e117393172aae2d");
var ct:ByteArray = Hex.toArray("3b79424c9c0dd436bace9e0ed4586a4f32b9");
var cfb8:CFB8Mode = new CFB8Mode(new AESKey(key), new NullPad);
cfb8.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
cfb8.encrypt(src);
assert("CFB8_AES128 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
cfb8.decrypt(src);
assert("CFB8_AES128 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
public function testCFB8_AES192():void {
var key:ByteArray = Hex.toArray("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b");
var pt:ByteArray = Hex.toArray("6bc1bee22e409f96e93d7e117393172aae2d");
var ct:ByteArray = Hex.toArray("cda2521ef0a905ca44cd057cbf0d47a0678a");
var cfb8:CFB8Mode = new CFB8Mode(new AESKey(key), new NullPad);
cfb8.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
cfb8.encrypt(src);
assert("CFB8_AES128 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
cfb8.decrypt(src);
assert("CFB8_AES128 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
public function testCFB8_AES256():void {
var key:ByteArray = Hex.toArray("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4");
var pt:ByteArray = Hex.toArray("6bc1bee22e409f96e93d7e117393172aae2d");
var ct:ByteArray = Hex.toArray("dc1f1a8520a64db55fcc8ac554844e889700");
var cfb8:CFB8Mode = new CFB8Mode(new AESKey(key), new NullPad);
cfb8.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
cfb8.encrypt(src);
assert("CFB8_AES128 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
cfb8.decrypt(src);
assert("CFB8_AES128 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
}
}

View file

@ -1,98 +0,0 @@
/**
* CFBModeTest
*
* A test class for CFBMode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import com.hurlant.crypto.symmetric.AESKey;
import com.hurlant.crypto.symmetric.CFBMode;
import com.hurlant.crypto.symmetric.NullPad;
import com.hurlant.util.Hex;
import flash.utils.ByteArray;
public class CFBModeTest extends TestCase
{
public function CFBModeTest(h:ITestHarness)
{
super(h, "CFBMode Test");
runTest(testCFB_AES128, "CFB AES-128 Test Vectors");
runTest(testCFB_AES192, "CFB AES-192 Test Vectors");
runTest(testCFB_AES256, "CFB AES-256 Test Vectors");
h.endTestCase();
}
/**
* http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
*/
public function testCFB_AES128():void {
var key:ByteArray = Hex.toArray("2b7e151628aed2a6abf7158809cf4f3c");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"3b3fd92eb72dad20333449f8e83cfb4a" +
"c8a64537a0b3a93fcde3cdad9f1ce58b" +
"26751f67a3cbb140b1808cf187a4f4df" +
"c04b05357c5d1c0eeac4c66f9ff7f2e6");
var cfb:CFBMode = new CFBMode(new AESKey(key), new NullPad);
cfb.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
cfb.encrypt(src);
assert("CFB_AES128 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
cfb.decrypt(src);
assert("CFB_AES128 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
public function testCFB_AES192():void {
var key:ByteArray = Hex.toArray("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"cdc80d6fddf18cab34c25909c99a4174" +
"67ce7f7f81173621961a2b70171d3d7a" +
"2e1e8a1dd59b88b1c8e60fed1efac4c9" +
"c05f9f9ca9834fa042ae8fba584b09ff");
var cfb:CFBMode = new CFBMode(new AESKey(key), new NullPad);
cfb.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
cfb.encrypt(src);
assert("CFB_AES192 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
cfb.decrypt(src);
assert("CFB_AES192 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
public function testCFB_AES256():void {
var key:ByteArray = Hex.toArray(
"603deb1015ca71be2b73aef0857d7781" +
"1f352c073b6108d72d9810a30914dff4");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"dc7e84bfda79164b7ecd8486985d3860" +
"39ffed143b28b1c832113c6331e5407b" +
"df10132415e54b92a13ed0a8267ae2f9" +
"75a385741ab9cef82031623d55b1e471");
var cfb:CFBMode = new CFBMode(new AESKey(key), new NullPad);
cfb.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
cfb.encrypt(src);
assert("CFB_AES256 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
cfb.decrypt(src);
assert("CFB_AES256 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
}
}

View file

@ -1,109 +0,0 @@
/**
* CTRModeTest
*
* A test class for CTRMode
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import flash.utils.ByteArray;
import com.hurlant.util.Hex;
import com.hurlant.crypto.symmetric.CTRMode;
import com.hurlant.crypto.symmetric.AESKey;
import com.hurlant.crypto.symmetric.NullPad;
public class CTRModeTest extends TestCase
{
public function CTRModeTest(h:ITestHarness)
{
super(h, "CTRMode Test");
runTest(testCTR_AES128, "CTR AES-128 Test Vectors");
runTest(testCTR_AES192, "CTR AES-192 Test Vectors");
runTest(testCTR_AES256, "CTR AES-256 Test Vectors");
h.endTestCase();
}
/**
* Vectors from http://csrc.nist.gov/CryptoToolkit/modes/800-38_Series_Publications/SP800-38A.pdf
* Section F.5.1 and below.
*/
public function testCTR_AES128():void {
var key:ByteArray = Hex.toArray("2b7e151628aed2a6abf7158809cf4f3c");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"874d6191b620e3261bef6864990db6ce" +
"9806f66b7970fdff8617187bb9fffdff" +
"5ae4df3edbd5d35e5b4f09020db03eab" +
"1e031dda2fbe03d1792170a0f3009cee");
var ctr:CTRMode = new CTRMode(new AESKey(key), new NullPad);
ctr.IV = Hex.toArray("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
ctr.encrypt(src);
var hsrc:String = Hex.fromArray(src);
var hct:String = Hex.fromArray(ct);
assert("CTR_AES128 test 1: "+hsrc+" != "+hct, hsrc==hct);
ctr.decrypt(src);
hsrc = Hex.fromArray(src);
var hpt:String = Hex.fromArray(pt);
assert("CTR_AES128 test 2: "+hsrc+" != "+hpt, hsrc==hpt);
}
public function testCTR_AES192():void {
var key:ByteArray = Hex.toArray("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"1abc932417521ca24f2b0459fe7e6e0b" +
"090339ec0aa6faefd5ccc2c6f4ce8e94" +
"1e36b26bd1ebc670d1bd1d665620abf7" +
"4f78a7f6d29809585a97daec58c6b050");
var ctr:CTRMode = new CTRMode(new AESKey(key), new NullPad);
ctr.IV = Hex.toArray("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
ctr.encrypt(src);
var hsrc:String = Hex.fromArray(src);
var hct:String = Hex.fromArray(ct);
assert("CTR_AES192 test 1: "+hsrc+" != "+hct, hsrc==hct);
ctr.decrypt(src);
hsrc = Hex.fromArray(src);
var hpt:String = Hex.fromArray(pt);
assert("CTR_AES192 test 2: "+hsrc+" != "+hpt, hsrc==hpt);
}
public function testCTR_AES256():void {
var key:ByteArray = Hex.toArray("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"601ec313775789a5b7a7f504bbf3d228" +
"f443e3ca4d62b59aca84e990cacaf5c5" +
"2b0930daa23de94ce87017ba2d84988d" +
"dfc9c58db67aada613c2dd08457941a6");
var ctr:CTRMode = new CTRMode(new AESKey(key), new NullPad);
ctr.IV = Hex.toArray("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
ctr.encrypt(src);
var hsrc:String = Hex.fromArray(src);
var hct:String = Hex.fromArray(ct);
assert("CTR_AES256 test 1: "+hsrc+" != "+hct, hsrc==hct);
ctr.decrypt(src);
hsrc = Hex.fromArray(src);
var hpt:String = Hex.fromArray(pt);
assert("CTR_AES256 test 2: "+hsrc+" != "+hpt, hsrc==hpt);
}
}
}

View file

@ -1,112 +0,0 @@
/**
* DesKeyTest
*
* A test class for DesKey
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import com.hurlant.crypto.symmetric.DESKey;
import com.hurlant.util.Hex;
import flash.utils.ByteArray;
public class DESKeyTest extends TestCase
{
public function DESKeyTest(h:ITestHarness)
{
super(h, "DESKey Test");
runTest(testECB,"DES ECB Test Vectors");
h.endTestCase();
}
/**
* Test vectors mostly grabbed from
* http://csrc.nist.gov/publications/nistpubs/800-17/800-17.pdf
* (Appendix A and B)
* incomplete.
*/
public function testECB():void {
var keys:Array = [
"3b3898371520f75e", // grabbed from the output of some js implementation out there
"10316E028C8F3B4A", // appendix A vector
"0101010101010101", // appendix B Table 1, round 0
"0101010101010101", // round 1
"0101010101010101", // 2
"0101010101010101",
"0101010101010101",
"0101010101010101",
"0101010101010101",
"0101010101010101",
"0101010101010101", // round 8
"8001010101010101", // app B, tbl 2, round 0
"4001010101010101",
"2001010101010101",
"1001010101010101",
"0801010101010101",
"0401010101010101",
"0201010101010101",
"0180010101010101",
"0140010101010101", // round 8
];
var pts:Array = [
"0000000000000000", // js
"0000000000000000", // App A
"8000000000000000", // App B, tbl 1, rnd0
"4000000000000000",
"2000000000000000",
"1000000000000000",
"0800000000000000", // rnd 4
"0400000000000000",
"0200000000000000",
"0100000000000000",
"0080000000000000", // round 8
"0000000000000000", // App B, tbl2, rnd0
"0000000000000000",
"0000000000000000",
"0000000000000000",
"0000000000000000",
"0000000000000000",
"0000000000000000",
"0000000000000000",
"0000000000000000", // rnd 8
];
var cts:Array = [
"83A1E814889253E0", // js
"82DCBAFBDEAB6602", // App A
"95F8A5E5DD31D900", // App b, tbl 1, rnd 0
"DD7F121CA5015619",
"2E8653104F3834EA",
"4BD388FF6CD81D4F",
"20B9E767B2FB1456",
"55579380D77138EF",
"6CC5DEFAAF04512F",
"0D9F279BA5D87260",
"D9031B0271BD5A0A", // rnd 8
"95A8D72813DAA94D", // App B, tbl 2, rnd 0
"0EEC1487DD8C26D5",
"7AD16FFB79C45926",
"D3746294CA6A6CF3",
"809F5F873C1FD761",
"C02FAFFEC989D1FC",
"4615AA1D33E72F10",
"2055123350C00858",
"DF3B99D6577397C8", // rnd 8
];
for (var i:uint=0;i<keys.length;i++) {
var key:ByteArray = Hex.toArray(keys[i]);
var pt:ByteArray = Hex.toArray(pts[i]);
var des:DESKey = new DESKey(key);
des.encrypt(pt);
var out:String = Hex.fromArray(pt).toUpperCase();
assert("comparing "+cts[i]+" to "+out, cts[i]==out);
// now go back to plaintext
des.decrypt(pt);
out = Hex.fromArray(pt).toUpperCase();
assert("comparing "+pts[i]+" to "+out, pts[i]==out);
}
}
}
}

View file

@ -1,151 +0,0 @@
/**
* ECBModeTest
*
* A test class for ECBMode
* 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.ECBMode;
import com.hurlant.crypto.symmetric.NullPad;
import com.hurlant.crypto.symmetric.XTeaKey;
import com.hurlant.util.Hex;
import flash.utils.ByteArray;
public class ECBModeTest extends TestCase
{
public function ECBModeTest(h:ITestHarness) {
super(h, "ECBMode Test");
runTest(testAES,"ECB AES Test Vectors");
runTest(testXTea,"ECB XTea Test Vectors");
runTest(testECB_AES128,"ECB AES-128 Test Vectors");
runTest(testECB_AES192,"ECB AES-192 Test Vectors");
runTest(testECB_AES256,"ECB AES-256 Test Vectors");
h.endTestCase();
}
/**
* 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.
* yay. found hawt test vectors: http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
*/
public function testECB_AES128():void {
var key:ByteArray = Hex.toArray("2b7e151628aed2a6abf7158809cf4f3c");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"3ad77bb40d7a3660a89ecaf32466ef97" +
"f5d3d58503b9699de785895a96fdbaaf" +
"43b1cd7f598ece23881b00e3ed030688" +
"7b0c785e27e8ad3f8223207104725dd4");
var ecb:ECBMode = new ECBMode(new AESKey(key), new NullPad);
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
ecb.encrypt(src);
assert("ECB_AES128 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
ecb.decrypt(src);
assert("ECB_AES128 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
public function testECB_AES192():void {
var key:ByteArray = Hex.toArray("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"bd334f1d6e45f25ff712a214571fa5cc" +
"974104846d0ad3ad7734ecb3ecee4eef" +
"ef7afd2270e2e60adce0ba2face6444e" +
"9a4b41ba738d6c72fb16691603c18e0e");
var ecb:ECBMode = new ECBMode(new AESKey(key), new NullPad);
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
ecb.encrypt(src);
assert("ECB_AES192 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
ecb.decrypt(src);
assert("ECB_AES192 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
public function testECB_AES256():void {
var key:ByteArray = Hex.toArray(
"603deb1015ca71be2b73aef0857d7781" +
"1f352c073b6108d72d9810a30914dff4");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"f3eed1bdb5d2a03c064b5a7e3db181f8" +
"591ccb10d410ed26dc5ba74a31362870" +
"b6ed21b99ca6f4f9f153e7b1beafed1d" +
"23304b7a39f9f3ff067d8d8f9e24ecc7");
var ecb:ECBMode = new ECBMode(new AESKey(key), new NullPad);
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
ecb.encrypt(src);
assert("ECB_AES256 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
ecb.decrypt(src);
assert("ECB_AES256 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
// crappier, older testing. keeping around for no good reason.
public function testAES():void {
var keys:Array = [
"00010203050607080A0B0C0D0F101112",
"14151617191A1B1C1E1F202123242526"];
var pts:Array = [
"506812A45F08C889B97F5980038B8359506812A45F08C889B97F5980038B8359506812A45F08C889B97F5980038B8359",
"5C6D71CA30DE8B8B00549984D2EC7D4B5C6D71CA30DE8B8B00549984D2EC7D4B5C6D71CA30DE8B8B00549984D2EC7D4B"];
var cts:Array = [
"D8F532538289EF7D06B506A4FD5BE9C9D8F532538289EF7D06B506A4FD5BE9C9D8F532538289EF7D06B506A4FD5BE9C96DE5F607AB7EB8202F3957703B04E8B5",
"59AB30F4D4EE6E4FF9907EF65B1FB68C59AB30F4D4EE6E4FF9907EF65B1FB68C59AB30F4D4EE6E4FF9907EF65B1FB68C2993487785CB1CFDA6BB4F0F345F76C7"];
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 ecb:ECBMode = new ECBMode(aes);
ecb.encrypt(pt);
var str:String = Hex.fromArray(pt).toUpperCase();
assert("comparing "+cts[i]+" to "+str, cts[i]==str);
// back to pt
ecb.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 pts:Array=[
"0000000000000000000000000000000000000000000000000000000000000000",
"74657374206d652e74657374206d652e74657374206d652e74657374206d652e"];
var cts:Array=[
"2dc7e8d3695b05382dc7e8d3695b05382dc7e8d3695b05382dc7e8d3695b053820578a874233632d",
"79095821381987837909582138198783790958213819878379095821381987830e4dc3c48b2edf32"];
// self-fullfilling vectors.
// oh well, at least I can decrypt what I produce. :(
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 ecb:ECBMode = new ECBMode(tea);
ecb.encrypt(pt);
var str:String = Hex.fromArray(pt);
assert("comparing "+cts[i]+" to "+str, cts[i]==str);
// now go back to plaintext.
ecb.decrypt(pt);
str = Hex.fromArray(pt);
assert("comparing "+pts[i]+" to "+str, pts[i]==str);
}
}
}
}

View file

@ -1,184 +0,0 @@
/**
* HMACTest
*
* A test class for HMAC
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import com.hurlant.crypto.hash.HMAC;
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.util.Hex;
import flash.utils.ByteArray;
public class HMACTest extends TestCase
{
public function HMACTest(h:ITestHarness)
{
super(h, "HMAC Test");
runTest(testHMAC_MD5,"HMAC MD5 Test Vectors");
runTest(testHMAC_SHA_1,"HMAC SHA-1 Test Vectors");
runTest(testHMAC_SHA_2,"HMAC SHA-224/SHA-256 Test Vectors");
runTest(testHMAC96_MD5,"HMAC-96 MD5 Test Vectors");
runTest(testHMAC96_SHA_1,"HMAC-96 SHA-1 Test Vectors");
runTest(testHMAC128_SHA_2,"HMAC-128 SHA-224/SHA-256 Test Vectors");
h.endTestCase();
}
/**
* Test vectors taking from RFC2202
* http://tools.ietf.org/html/rfc2202
* Yes, it's from an RFC, jefe! Now waddayawant?
*/
public function testHMAC_SHA_1():void {
var keys:Array = [
"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
Hex.fromString("Jefe"),
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"0102030405060708090a0b0c0d0e0f10111213141516171819",
"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"];
var pts:Array = [
Hex.fromString("Hi There"),
Hex.fromString("what do ya want for nothing?"),
"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
"cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
Hex.fromString("Test With Truncation"),
Hex.fromString("Test Using Larger Than Block-Size Key - Hash Key First"),
Hex.fromString("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data")];
var cts:Array = [
"b617318655057264e28bc0b6fb378c8ef146be00",
"effcdf6ae5eb2fa2d27416d5f184df9c259a7c79",
"125d7342b9ac11cd91a39af48aa17b4f63f175d3",
"4c9007f4026250c6bc8414f9bf50c86c2d7235da",
"4c1a03424b55e07fe7f27be1d58bb9324a9a5a04",
"aa4ae5e15272d00e95705637ce8a3b55ed402112",
"e8e99d0f45237d786d6bbaa7965c7808bbff1a91"];
var hmac:HMAC = new HMAC(new SHA1());
for (var i:uint=0;i<keys.length;i++) {
var key:ByteArray = Hex.toArray(keys[i]);
var pt:ByteArray = Hex.toArray(pts[i]);
var digest:ByteArray = hmac.compute(key, pt);
assert("HMAC-SHA-1 test "+i, Hex.fromArray(digest) == cts[i]);
}
}
public function testHMAC96_SHA_1():void {
var hmac:HMAC = new HMAC(new SHA1, 96);
var key:ByteArray = Hex.toArray("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c");
var pt:ByteArray = Hex.toArray(Hex.fromString("Test With Truncation"));
var ct:String = "4c1a03424b55e07fe7f27be1";
var digest:ByteArray = hmac.compute(key, pt);
assert("HMAC96-SHA-1 test", Hex.fromArray(digest) == ct);
}
public function testHMAC_MD5():void {
var keys:Array = [
Hex.fromString("Jefe"),
"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"0102030405060708090a0b0c0d0e0f10111213141516171819",
"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"];
var pts:Array = [
Hex.fromString("what do ya want for nothing?"),
Hex.fromString("Hi There"),
"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
"cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
Hex.fromString("Test With Truncation"),
Hex.fromString("Test Using Larger Than Block-Size Key - Hash Key First"),
Hex.fromString("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data")];
var cts:Array = [
"750c783e6ab0b503eaa86e310a5db738",
"9294727a3638bb1c13f48ef8158bfc9d",
"56be34521d144c88dbb8c733f0e8b3f6",
"697eaf0aca3a3aea3a75164746ffaa79",
"56461ef2342edc00f9bab995690efd4c",
"6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd",
"6f630fad67cda0ee1fb1f562db3aa53e"];
var hmac:HMAC = new HMAC(new MD5());
for (var i:uint=0;i<keys.length;i++) {
var key:ByteArray = Hex.toArray(keys[i]);
var pt:ByteArray = Hex.toArray(pts[i]);
var digest:ByteArray = hmac.compute(key, pt);
assert("HMAC-MD5 test "+i, Hex.fromArray(digest) == cts[i]);
}
}
public function testHMAC96_MD5():void {
var hmac:HMAC = new HMAC(new MD5, 96);
var key:ByteArray = Hex.toArray("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c");
var pt:ByteArray = Hex.toArray(Hex.fromString("Test With Truncation"));
var ct:String = "56461ef2342edc00f9bab995";
var digest:ByteArray = hmac.compute(key, pt);
assert("HMAC96-MD5 test", Hex.fromArray(digest) == ct);
}
/**
* Test vectors for HMAC-SHA-2 taken from RFC4231
* http://www.ietf.org/rfc/rfc4231.txt
* Still the same lame strings, but hidden in hex. why not.
*/
public function testHMAC_SHA_2():void {
var keys:Array = [
"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
"4a656665",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"0102030405060708090a0b0c0d0e0f10111213141516171819",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"];
var pts:Array = [
"4869205468657265",
"7768617420646f2079612077616e7420666f72206e6f7468696e673f",
"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
"cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
"54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374",
"5468697320697320612074657374207573696e672061206c6172676572207468616e20626c6f636b2d73697a65206b657920616e642061206c6172676572207468616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565647320746f20626520686173686564206265666f7265206265696e6720757365642062792074686520484d414320616c676f726974686d2e"];
var cts224:Array = [
"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22",
"a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44",
"7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea",
"6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a",
"95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e",
"3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1"];
var cts256:Array = [
"b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7",
"5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
"773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe",
"82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b",
"60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54",
"9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2"];
// 384 and 512 will be added. someday. if I ever figure how to do 64bit computations half efficiently in as3
var hmac224:HMAC = new HMAC(new SHA224);
var hmac256:HMAC = new HMAC(new SHA256);
for (var i:uint=0;i<keys.length;i++) {
var key:ByteArray = Hex.toArray(keys[i]);
var pt:ByteArray = Hex.toArray(pts[i]);
var digest224:ByteArray = hmac224.compute(key, pt);
assert("HMAC-SHA-224 test "+i, Hex.fromArray(digest224) == cts224[i]);
var digest256:ByteArray = hmac256.compute(key, pt);
assert("HMAC-SHA-256 test "+i, Hex.fromArray(digest256) == cts256[i]);
}
}
public function testHMAC128_SHA_2():void {
var hmac224:HMAC = new HMAC(new SHA224,128);
var hmac256:HMAC = new HMAC(new SHA256,128);
var key:ByteArray = Hex.toArray("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c");
var pt:ByteArray = Hex.toArray("546573742057697468205472756e636174696f6e");
var ct224:String = "0e2aea68a90c8d37c988bcdb9fca6fa8";
var ct256:String = "a3b6167473100ee06e0c796c2955552b";
var digest224:ByteArray = hmac224.compute(key, pt);
assert("HMAC128-SHA-224 test", Hex.fromArray(digest224) == ct224);
var digest256:ByteArray = hmac256.compute(key, pt);
assert("HMAC128-SHA-256 test", Hex.fromArray(digest256) == ct256);
}
}
}

View file

@ -1,20 +0,0 @@
/**
* ITestHarness
*
* An interface to specify what's available for test cases to use.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
public interface ITestHarness
{
function beginTestCase(name:String):void;
function endTestCase():void;
function beginTest(name:String):void;
function passTest():void;
function failTest(msg:String):void;
}
}

View file

@ -1,56 +0,0 @@
/**
* MD2Test
*
* A test class for MD2
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import com.hurlant.crypto.hash.MD2;
import com.hurlant.util.Hex;
import flash.utils.ByteArray;
public class MD2Test extends TestCase
{
public function MD2Test(h:ITestHarness)
{
super(h, "MD2 Test");
runTest(testMd2, "MD2 Test Vectors");
h.endTestCase();
}
/**
* Test Vectors grabbed from
* http://www.faqs.org/rfcs/rfc1319.html
*/
public function testMd2():void {
var srcs:Array = [
"",
Hex.fromString("a"),
Hex.fromString("abc"),
Hex.fromString("message digest"),
Hex.fromString("abcdefghijklmnopqrstuvwxyz"),
Hex.fromString("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"),
Hex.fromString("12345678901234567890123456789012345678901234567890123456789012345678901234567890")
];
var hashes:Array = [
"8350e5a3e24c153df2275c9f80692773",
"32ec01ec4a6dac72c0ab96fb34c0b5d1",
"da853b0d3f88d99b30283a69e6ded6bb",
"ab4f496bfb2a530b219ff33031fe06b0",
"4e8ddff3650292ab5a4108c3aa47940b",
"da33def2a42df13975352846c30338cd",
"d5976f79d83d3a0dc9806c3c66f3efd8"
];
var md2:MD2 = new MD2;
for (var i:uint=0;i<srcs.length;i++) {
var src:ByteArray = Hex.toArray(srcs[i]);
var digest:ByteArray = md2.hash(src);
assert("MD2 Test "+i, Hex.fromArray(digest) == hashes[i]);
}
}
}
}

View file

@ -1,58 +0,0 @@
/**
* MD5Test
*
* A test class for MD5
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import com.hurlant.crypto.hash.MD5;
import com.hurlant.util.Hex;
import flash.utils.ByteArray;
public class MD5Test extends TestCase
{
public function MD5Test(h:ITestHarness)
{
super(h, "MD5 Test");
runTest(testMd5,"MD5 Test Vectors");
h.endTestCase();
}
/**
* Test Vectors grabbed from
* http://www.faqs.org/rfcs/rfc1321.html
*/
public function testMd5():void {
var srcs:Array = [
"",
Hex.fromString("a"),
Hex.fromString("abc"),
Hex.fromString("message digest"),
Hex.fromString("abcdefghijklmnopqrstuvwxyz"),
Hex.fromString("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"),
Hex.fromString("12345678901234567890123456789012345678901234567890123456789012345678901234567890")
];
var hashes:Array = [
"d41d8cd98f00b204e9800998ecf8427e",
"0cc175b9c0f1b6a831c399e269772661",
"900150983cd24fb0d6963f7d28e17f72",
"f96b697d7cb7938d525a2f31aaf161d0",
"c3fcd3d76192e4007dfb496cca67e13b",
"d174ab98d277d9f5a5611c2c9f419d9f",
"57edf4a22be3c955ac49da2e2107b67a"
];
var md5:MD5 = new MD5;
for (var i:uint=0;i<srcs.length;i++) {
var src:ByteArray = Hex.toArray(srcs[i]);
var digest:ByteArray = md5.hash(src);
assert("MD5 Test "+i, Hex.fromArray(digest) == hashes[i]);
}
}
}
}

View file

@ -1,101 +0,0 @@
/**
* OFBModeTest
*
* A test class for OFBMode
* 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.OFBMode;
import com.hurlant.crypto.symmetric.AESKey;
import com.hurlant.crypto.symmetric.NullPad;
public class OFBModeTest extends TestCase
{
public function OFBModeTest(h:ITestHarness)
{
super(h, "OFBMode Test");
runTest(testOFB_AES128,"OFB AES-128 Test Vectors");
runTest(testOFB_AES192,"OFB AES-192 Test Vectors");
runTest(testOFB_AES256,"OFB AES-256 Test Vectors");
h.endTestCase();
}
/**
* Nist Vectors: http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
* Section F.4.1 and below.
*/
public function testOFB_AES128():void {
var key:ByteArray = Hex.toArray("2b7e151628aed2a6abf7158809cf4f3c");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"3b3fd92eb72dad20333449f8e83cfb4a" +
"7789508d16918f03f53c52dac54ed825" +
"9740051e9c5fecf64344f7a82260edcc" +
"304c6528f659c77866a510d9c1d6ae5e");
var ofb:OFBMode = new OFBMode(new AESKey(key), new NullPad);
ofb.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
ofb.encrypt(src);
assert("OFB_AES128 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
ofb.decrypt(src);
assert("OFB_AES128 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
public function testOFB_AES192():void {
var key:ByteArray = Hex.toArray("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"cdc80d6fddf18cab34c25909c99a4174" +
"fcc28b8d4c63837c09e81700c1100401" +
"8d9a9aeac0f6596f559c6d4daf59a5f2" +
"6d9f200857ca6c3e9cac524bd9acc92a");
var ofb:OFBMode = new OFBMode(new AESKey(key), new NullPad);
ofb.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
ofb.encrypt(src);
assert("OFB_AES192 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
ofb.decrypt(src);
assert("OFB_AES192 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
public function testOFB_AES256():void {
var key:ByteArray = Hex.toArray(
"603deb1015ca71be2b73aef0857d7781" +
"1f352c073b6108d72d9810a30914dff4");
var pt:ByteArray = Hex.toArray(
"6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710");
var ct:ByteArray = Hex.toArray(
"dc7e84bfda79164b7ecd8486985d3860" +
"4febdc6740d20b3ac88f6ad82a4fb08d" +
"71ab47a086e86eedf39d1c5bba97c408" +
"0126141d67f37be8538f5a8be740e484");
var ofb:OFBMode = new OFBMode(new AESKey(key), new NullPad);
ofb.IV = Hex.toArray("000102030405060708090a0b0c0d0e0f");
var src:ByteArray = new ByteArray;
src.writeBytes(pt);
ofb.encrypt(src);
assert("OFB_AES256 test 1", Hex.fromArray(src)==Hex.fromArray(ct));
ofb.decrypt(src);
assert("OFB_AES256 test 2", Hex.fromArray(src)==Hex.fromArray(pt));
}
}
}

View file

@ -1,92 +0,0 @@
/**
* RSAKeyTest
*
* A test class for RSAKey
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import com.hurlant.crypto.rsa.RSAKey;
import flash.utils.ByteArray;
import com.hurlant.util.Hex;
import com.hurlant.util.der.PEM;
public class RSAKeyTest extends TestCase
{
public function RSAKeyTest(h:ITestHarness)
{
super(h, "RSA Testing");
runTest(testSmoke,"RSA smoke test");
runTest(testGenerate, "RSA Key Generation test");
runTest(testPEM, "RSA Private Key PEM parsing");
runTest(testPEM2, "RSA Public Key PEM parsing");
h.endTestCase();
}
public function testSmoke():void {
var N:String ="C4E3F7212602E1E396C0B6623CF11D26204ACE3E7D26685E037AD2507DCE82FC" +
"28F2D5F8A67FC3AFAB89A6D818D1F4C28CFA548418BD9F8E7426789A67E73E41";
var E:String = "10001";
var D:String = "7cd1745aec69096129b1f42da52ac9eae0afebbe0bc2ec89253598dcf454960e" +
"3e5e4ec9f8c87202b986601dd167253ee3fb3fa047e14f1dfd5ccd37e931b29d";
var P:String = "f0e4dd1eac5622bd3932860fc749bbc48662edabdf3d2826059acc0251ac0d3b";
var Q:String = "d13cb38fbcd06ee9bca330b4000b3dae5dae12b27e5173e4d888c325cda61ab3";
var DMP1:String = "b3d5571197fc31b0eb6b4153b425e24c033b054d22b9c8282254fe69d8c8c593";
var DMQ1:String = "968ffe89e50d7b72585a79b65cfdb9c1da0963cceb56c3759e57334de5a0ac3f";
var IQMP:String = "d9bc4f420e93adad9f007d0e5744c2fe051c9ed9d3c9b65f439a18e13d6e3908";
// create a key.
var rsa:RSAKey = RSAKey.parsePrivateKey(N,E,D, P,Q,DMP1,DMQ1,IQMP);
var txt:String = "hello";
var src:ByteArray = Hex.toArray(Hex.fromString(txt));
var dst:ByteArray = new ByteArray;
var dst2:ByteArray = new ByteArray;
rsa.encrypt(src, dst, src.length);
rsa.decrypt(dst, dst2, dst.length);
var txt2:String = Hex.toString(Hex.fromArray(dst2));
assert("rsa encrypt+decrypt", txt==txt2);
}
public function testGenerate():void {
var rsa:RSAKey = RSAKey.generate(256, "10001");
// same lame smoke test here.
var txt:String = "hello";
var src:ByteArray = Hex.toArray(Hex.fromString(txt));
var dst:ByteArray = new ByteArray;
var dst2:ByteArray = new ByteArray;
rsa.encrypt(src, dst, src.length);
rsa.decrypt(dst, dst2, dst.length);
var txt2:String = Hex.toString(Hex.fromArray(dst2));
assert("rsa encrypt+decrypt", txt==txt2);
}
public function testPEM():void {
var pem:String = "-----BEGIN RSA PRIVATE KEY-----\n" +
"MGQCAQACEQDJG3bkuB9Ie7jOldQTVdzPAgMBAAECEQCOGqcPhP8t8mX8cb4cQEaR\n" +
"AgkA5WTYuAGmH0cCCQDgbrto0i7qOQIINYr5btGrtccCCQCYy4qX4JDEMQIJAJll\n" +
"OnLVtCWk\n" +
"-----END RSA PRIVATE KEY-----";
var rsa:RSAKey = PEM.readRSAPrivateKey(pem);
//trace(rsa.dump());
// obligatory use
var txt:String = "hello";
var src:ByteArray = Hex.toArray(Hex.fromString(txt));
var dst:ByteArray = new ByteArray;
var dst2:ByteArray = new ByteArray;
rsa.encrypt(src, dst, src.length);
rsa.decrypt(dst, dst2, dst.length);
var txt2:String = Hex.toString(Hex.fromArray(dst2));
assert("rsa encrypt+decrypt", txt==txt2);
}
public function testPEM2():void {
var pem:String = "-----BEGIN PUBLIC KEY-----\n" +
"MCwwDQYJKoZIhvcNAQEBBQADGwAwGAIRAMkbduS4H0h7uM6V1BNV3M8CAwEAAQ==\n" +
"-----END PUBLIC KEY-----";
var rsa:RSAKey = PEM.readRSAPublicKey(pem);
//trace(rsa.dump());
}
}
}

View file

@ -1,198 +0,0 @@
/**
* SHA1Test
*
* A test class for SHA1
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import com.hurlant.crypto.hash.SHA1;
import com.hurlant.util.Hex;
import flash.utils.ByteArray;
public class SHA1Test extends TestCase
{
public function SHA1Test(h:ITestHarness)
{
super(h, "SHA-1 Test");
runTest(testSha1,"SHA-1 Test Vectors");
runTest(testLongSha1,"SHA-1 Long Test Vectors");
h.endTestCase();
}
/**
* Test Vectors grabbed from
* http://csrc.nist.gov/cryptval/shs.htm
*/
public function testSha1():void {
var srcs:Array = [
"",
"a8",
"3000",
"42749e",
"9fc3fe08",
"b5c1c6f1af",
"e47571e5022e",
"3e1b28839fb758",
"a81350cbb224cb90",
"c243d167923dec3ce1",
"50ac18c59d6a37a29bf4",
"98e2b611ad3b1cccf634f6",
"73fe9afb68e1e8712e5d4eec",
"9e701ed7d412a9226a2a130e66",
"6d3ee90413b0a7cbf69e5e6144ca",
"fae24d56514efcb530fd4802f5e71f",
"c5a22dd6eda3fe2bdc4ddb3ce6b35fd1",
"d98cded2adabf08fda356445c781802d95",
"bcc6d7087a84f00103ccb32e5f5487a751a2",
"36ecacb1055434190dbbc556c48bafcb0feb0d",
"5ff9edb69e8f6bbd498eb4537580b7fba7ad31d0",
"c95b441d8270822a46a798fae5defcf7b26abace36",
"83104c1d8a55b28f906f1b72cb53f68cbb097b44f860",
"755175528d55c39c56493d697b790f099a5ce741f7754b",
"088fc38128bbdb9fd7d65228b3184b3faac6c8715f07272f",
"a4a586eb9245a6c87e3adf1009ac8a49f46c07e14185016895",
"8e7c555270c006092c2a3189e2a526b873e2e269f0fb28245256",
"a5f3bfa6bb0ba3b59f6b9cbdef8a558ec565e8aa3121f405e7f2f0",
"589054f0d2bd3c2c85b466bfd8ce18e6ec3e0b87d944cd093ba36469",
"a0abb12083b5bbc78128601bf1cbdbc0fdf4b862b24d899953d8da0ff3",
"82143f4cea6fadbf998e128a8811dc75301cf1db4f079501ea568da68eeb",
"9f1231dd6df1ff7bc0b0d4f989d048672683ce35d956d2f57913046267e6f3",
"041c512b5eed791f80d3282f3a28df263bb1df95e1239a7650e5670fc2187919",
"17e81f6ae8c2e5579d69dafa6e070e7111461552d314b691e7a3e7a4feb3fae418",
"d15976b23a1d712ad28fad04d805f572026b54dd64961fda94d5355a0cc98620cf77",
"09fce4d434f6bd32a44e04b848ff50ec9f642a8a85b37a264dc73f130f22838443328f",
"f17af27d776ec82a257d8d46d2b46b639462c56984cc1be9c1222eadb8b26594a25c709d",
"b13ce635d6f8758143ffb114f2f601cb20b6276951416a2f94fbf4ad081779d79f4f195b22",
"5498793f60916ff1c918dde572cdea76da8629ba4ead6d065de3dfb48de94d234cc1c5002910",
"498a1e0b39fa49582ae688cd715c86fbaf8a81b8b11b4d1594c49c902d197c8ba8a621fd6e3be5",
"3a36ae71521f9af628b3e34dcb0d4513f84c78ee49f10416a98857150b8b15cb5c83afb4b570376e",
"dcc76b40ae0ea3ba253e92ac50fcde791662c5b6c948538cffc2d95e9de99cac34dfca38910db2678f",
"5b5ec6ec4fd3ad9c4906f65c747fd4233c11a1736b6b228b92e90cddabb0c7c2fcf9716d3fad261dff33",
"df48a37b29b1d6de4e94717d60cdb4293fcf170bba388bddf7a9035a15d433f20fd697c3e4c8b8c5f590ab",
"1f179b3b82250a65e1b0aee949e218e2f45c7a8dbfd6ba08de05c55acfc226b48c68d7f7057e5675cd96fcfc",
"ee3d72da3a44d971578972a8e6780ce64941267e0f7d0179b214fa97855e1790e888e09fbe3a70412176cb3b54",
"d4d4c7843d312b30f610b3682254c8be96d5f6684503f8fbfbcd15774fc1b084d3741afb8d24aaa8ab9c104f7258",
"32c094944f5936a190a0877fb9178a7bf60ceae36fd530671c5b38c5dbd5e6a6c0d615c2ac8ad04b213cc589541cf6",
"e5d3180c14bf27a5409fa12b104a8fd7e9639609bfde6ee82bbf9648be2546d29688a65e2e3f3da47a45ac14343c9c02",
"e7b6e4b69f724327e41e1188a37f4fe38b1dba19cbf5a7311d6e32f1038e97ab506ee05aebebc1eed09fc0e357109818b9",
"bc880cb83b8ac68ef2fedc2da95e7677ce2aa18b0e2d8b322701f67af7d5e7a0d96e9e33326ccb7747cfff0852b961bfd475",
"235ea9c2ba7af25400f2e98a47a291b0bccdaad63faa2475721fda5510cc7dad814bce8dabb611790a6abe56030b798b75c944",
"07e3e29fed63104b8410f323b975fd9fba53f636af8c4e68a53fb202ca35dd9ee07cb169ec5186292e44c27e5696a967f5e67709",
"65d2a1dd60a517eb27bfbf530cf6a5458f9d5f4730058bd9814379547f34241822bf67e6335a6d8b5ed06abf8841884c636a25733f",
"dcc86b3bd461615bab739d8daafac231c0f462e819ad29f9f14058f3ab5b75941d4241ea2f17ebb8a458831b37a9b16dead4a76a9b0e",
"4627d54f0568dc126b62a8c35fb46a9ac5024400f2995e51635636e1afc4373dbb848eb32df23914230560b82477e9c3572647a7f2bb92",
"ba531affd4381168ef24d8b275a84d9254c7f5cc55fded53aa8024b2c5c5c8aa7146fe1d1b83d62b70467e9a2e2cb67b3361830adbab28d7",
"8764dcbcf89dcf4282eb644e3d568bdccb4b13508bfa7bfe0ffc05efd1390be22109969262992d377691eb4f77f3d59ea8466a74abf57b2ef4",
"497d9df9ddb554f3d17870b1a31986c1be277bc44feff713544217a9f579623d18b5ffae306c25a45521d2759a72c0459b58957255ab592f3be4",
"72c3c2e065aefa8d9f7a65229e818176eef05da83f835107ba90ec2e95472e73e538f783b416c04654ba8909f26a12db6e5c4e376b7615e4a25819",
"7cc9894454d0055ab5069a33984e2f712bef7e3124960d33559f5f3b81906bb66fe64da13c153ca7f5cabc89667314c32c01036d12ecaf5f9a78de98",
"74e8404d5a453c5f4d306f2cfa338ca65501c840ddab3fb82117933483afd6913c56aaf8a0a0a6b2a342fc3d9dc7599f4a850dfa15d06c61966d74ea59",
"46fe5ed326c8fe376fcc92dc9e2714e2240d3253b105adfbb256ff7a19bc40975c604ad7c0071c4fd78a7cb64786e1bece548fa4833c04065fe593f6fb10",
"836dfa2524d621cf07c3d2908835de859e549d35030433c796b81272fd8bc0348e8ddbc7705a5ad1fdf2155b6bc48884ac0cd376925f069a37849c089c8645",
"7e3a4c325cb9c52b88387f93d01ae86d42098f5efa7f9457388b5e74b6d28b2438d42d8b64703324d4aa25ab6aad153ae30cd2b2af4d5e5c00a8a2d0220c6116"];
var hashes:Array = [
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"99f2aa95e36f95c2acb0eaf23998f030638f3f15",
"f944dcd635f9801f7ac90a407fbc479964dec024",
"a444319e9b6cc1e8464c511ec0969c37d6bb2619",
"16a0ff84fcc156fd5d3ca3a744f20a232d172253",
"fec9deebfcdedaf66dda525e1be43597a73a1f93",
"8ce051181f0ed5e9d0c498f6bc4caf448d20deb5",
"67da53837d89e03bf652ef09c369a3415937cfd3",
"305e4ff9888ad855a78573cddf4c5640cce7e946",
"5902b77b3265f023f9bbc396ba1a93fa3509bde7",
"fcade5f5d156bf6f9af97bdfa9c19bccfb4ff6ab",
"1d20fbe00533c10e3cbd6b27088a5de0c632c4b5",
"7e1b7e0f7a8f3455a9c03e9580fd63ae205a2d93",
"706f0677146307b20bb0e8d6311e329966884d13",
"a7241a703aaf0d53fe142f86bf2e849251fa8dff",
"400f53546916d33ad01a5e6df66822dfbdc4e9e6",
"fac8ab93c1ae6c16f0311872b984f729dc928ccd",
"fba6d750c18da58f6e2aab10112b9a5ef3301b3b",
"29d27c2d44c205c8107f0351b05753ac708226b6",
"b971bfc1ebd6f359e8d74cb7ecfe7f898d0ba845",
"96d08c430094b9fcc164ad2fb6f72d0a24268f68",
"a287ea752a593d5209e287881a09c49fa3f0beb1",
"a06c713779cbd88519ed4a585ac0cb8a5e9d612b",
"bff7d52c13a3688132a1d407b1ab40f5b5ace298",
"c7566b91d7b6f56bdfcaa9781a7b6841aacb17e9",
"ffa30c0b5c550ea4b1e34f8a60ec9295a1e06ac1",
"29e66ed23e914351e872aa761df6e4f1a07f4b81",
"b28cf5e5b806a01491d41f69bd9248765c5dc292",
"60224fb72c46069652cd78bcd08029ef64da62f3",
"b72c4a86f72608f24c05f3b9088ef92fba431df7",
"73779ad5d6b71b9b8328ef7220ff12eb167076ac",
"a09671d4452d7cf50015c914a1e31973d20cc1a0",
"e88cdcd233d99184a6fd260b8fca1b7f7687aee0",
"010def22850deb1168d525e8c84c28116cb8a269",
"aeaa40ba1717ed5439b1e6ea901b294ba500f9ad",
"c6433791238795e34f080a5f1f1723f065463ca0",
"e21e22b89c1bb944a32932e6b2a2f20d491982c3",
"575323a9661f5d28387964d2ba6ab92c17d05a8a",
"feb44494af72f245bfe68e86c4d7986d57c11db7",
"cff2290b3648ba2831b98dde436a72f9ebf51eee",
"9b4efe9d27b965905b0c3dab67b8d7c9ebacd56c",
"afedb0ff156205bcd831cbdbda43db8b0588c113",
"8deb1e858f88293a5e5e4d521a34b2a4efa70fc4",
"95cbdac0f74afa69cebd0e5c7defbc6faf0cbeaf",
"f0307bcb92842e5ae0cd4f4f14f3df7f877fbef2",
"7b13bb0dbf14964bd63b133ac85e22100542ef55",
"c314d2b6cf439be678d2a74e890d96cfac1c02ed",
"4d0be361e410b47a9d67d8ce0bb6a8e01c53c078",
"e5353431ffae097f675cbf498869f6fbb6e1c9f2",
"b8720a7068a085c018ab18961de2765aa6cd9ac4",
"b0732181568543ba85f2b6da602b4b065d9931aa",
"9c22674cf3222c3ba921672694aafee4ce67b96b",
"d128335f4cecca9066cdae08958ce656ff0b4cfc",
"0b67c57ac578de88a2ae055caeaec8bb9b0085a0",
"c766f912a89d4ccda88e0cce6a713ef5f178b596",
"9aa3925a9dcb177b15ccff9b78e70cf344858779",
"4811fa30042fc076acf37c8e2274d025307e5943",
"6743018450c9730761ee2b130df9b91c1e118150",
"71ad4a19d37d92a5e6ef3694ddbeb5aa61ada645",
"a7d9dc68dacefb7d6116186048cb355cc548e11d",
"142e429f0522ba5abf5131fa81df82d355b96909",
"ef72db70dcbcab991e9637976c6faf00d22caae9",
"f220a7457f4588d639dc21407c942e9843f8e26b",
"ddd2117b6e309c233ede85f962a0c2fc215e5c69",
"a3054427cdb13f164a610b348702724c808a0dcc"];
// ok. let's loop.
var sha1:SHA1 = new SHA1;
for (var i:uint=0;i<srcs.length;i++) {
var src:ByteArray = Hex.toArray(srcs[i]);
var digest:ByteArray = sha1.hash(src);
assert("SHA1 Test "+i, Hex.fromArray(digest) == hashes[i]);
}
}
/**
* A few long SHA-1, from the same page
*/
public function testLongSha1():void {
var srcs:Array = [
"ec29561244ede706b6eb30a1c371d74450a105c3f9735f7fa9fe38cf67f304a5736a106e92e17139a6813b1c81a4f3d3fb9546ab4296fa9f722826c066869edacd73b2548035185813e22634a9da44000d95a281ff9f264ecce0a931222162d021cca28db5f3c2aa24945ab1e31cb413ae29810fd794cad5dfaf29ec43cb38d198fe4ae1da2359780221405bd6712a5305da4b1b737fce7cd21c0eb7728d08235a9011",
"5fc2c3f6a7e79dc94be526e5166a238899d54927ce470018fbfd668fd9dd97cbf64e2c91584d01da63be3cc9fdff8adfefc3ac728e1e335b9cdc87f069172e323d094b47fa1e652afe4d6aa147a9f46fda33cacb65f3aa12234746b9007a8c85fe982afed7815221e43dba553d8fe8a022cdac1b99eeeea359e5a9d2e72e382dffa6d19f359f4f27dc3434cd27daeeda8e38594873398678065fbb23665aba9309d946135da0e4a4afdadff14db18e85e71dd93c3bf9faf7f25c8194c4269b1ee3d9934097ab990025d9c3aaf63d5109f52335dd3959d38ae485050e4bbb6235574fc0102be8f7a306d6e8de6ba6becf80f37415b57f9898a5824e77414197422be3d36a6080",
"0f865f46a8f3aed2da18482aa09a8f390dc9da07d51d1bd10fe0bf5f3928d5927d08733d32075535a6d1c8ac1b2dc6ba0f2f633dc1af68e3f0fa3d85e6c60cb7b56c239dc1519a007ea536a07b518ecca02a6c31b46b76f021620ef3fc6976804018380e5ab9c558ebfc5cb1c9ed2d974722bf8ab6398f1f2b82fa5083f85c16a5767a3a07271d67743f00850ce8ec428c7f22f1cf01f99895c0c844845b06a06cecb0c6cf83eb55a1d4ebc44c2c13f6f7aa5e0e08abfd84e7864279057abc471ee4a45dbbb5774afa24e51791a0eada11093b88681fe30baa3b2e94113dc63342c51ca5d1a6096d0897b626e42cb91761058008f746f35465465540ad8c6b8b60f7e1461b3ce9e6529625984cb8c7d46f07f735be067588a0117f23e34ff57800e2bbe9a1605fde6087fb15d22c5d3ac47566b8c448b0cee40373e5ba6eaa21abee71366afbb27dbbd300477d70c371e7b8963812f5ed4fb784fb2f3bd1d3afe883cdd47ef32beaea",
"4893f1c763625f2c6ce53aacf28026f14b3cd8687e1a1d3b60a81e80fcd1e2b038f9145ab64a0718f948f7c3c9ac92e3d86fb669a5257da1a18c776291653688338210a3242120f101788e8acc9110db9258b1554bf3d26602516ea93606a25a7f566c0c758fb39ecd9d876bc5d8abc1c3205095382c2474cb1f8bbdb45c2c0e659cb0fc703ec607a5de6bcc7a28687db1ee1c8f34797bb2441d5706d210df8c2d7d65dbded36414d063c117b52a51f7a4eb9cac0782e008b47459ed5acac0bc1f20121087f992ad985511b33c866d18e63f585478ee5a5e654b19d81231d98683ae3f0533565aba43dce408d7e3c4c6be11d8f05165f29c9dcb2030c4ee31d3a04e7421aa92c3231a1fc07e50e95fea7389a5e65891afaba51cf55e36a9d089bf293accb356d5d06547307d6e41456d4ed146a056179971c56521c83109bf922866186e184a99a96c7bb96df8937e35970e438412a2b8d744cf2ad87cb605d4232e976f9f15169776e4e5b6b786132c966b25fc56d815c56c819af5e159aa39f8a93d38115f5580cda93bc073c30b39920e726fe861b72483a3f886269ab7a8eefe952f35d25c4eb7f443f4f3f26e43d51fb54591e6a6dad25fcdf5142033084e5624bdd51435e77dea86b8",
"cf494c18a4e17bf03910631471bca5ba7edea8b9a63381e3463517961749848eb03abefd4ce676dece3740860255f57c261a558aa9c7f11432f549a9e4ce31d8e17c79450ce2ccfc148ad904aedfb138219d7052088520495355dadd90f72e6f69f9c6176d3d45f113f275b7fbc2a295784d41384cd7d629b23d1459a22e45fd5097ec9bf65fa965d3555ec77367903c32141065fc24da5c56963d46a2da3c279e4035fb2fb1c0025d9dda5b9e3443d457d92401a0d3f58b48469ecb1862dc975cdbe75ca099526db8b0329b03928206f084c633c04eef5e8e377f118d30edf592504be9d2802651ec78aeb02aea167a03fc3e23e5fc907c324f283f89ab37e84687a9c74ccf055402db95c29ba2c8d79b2bd4fa96459f8e3b78e07e923b81198267492196ecb71e01c331f8df245ec5bdf8d0e05c91e63bb299f0f6324895304dda721d39410458f117c87b7dd6a0ee734b79fcbe482b2c9e9aa0cef03a39d4b0c86de3bc34b4aadabfa373fd2258f7c40c187744d237080762382f547a36adb117839ca72f8ebbc5a20a07e86f4c8bb923f5787698d278f6db0040e76e54645bb0f97083995b34b9aa445fc424455058795828dd00c32471ec402a307f5aa1b37b1a86d6dae3bcbfbe9ba41cab0beeabf489af0073d4b3837d3f14b815120bc3602d072b5aeefcdec655fe756b660eba7dcf34675acbce317746270599424b9248791a0780449c1eabbb9459cc1e588bfd74df9b1b711c85c09d8aa171b309281947e8f4b6ac438753158f4f36fa"];
var hashes:Array = [
"970111c4e77bcc88cc20459c02b69b4aa8f58217",
"0423dc76a8791107d14e13f5265b343f24cc0f19",
"6692a71d73e00f27df976bc56df4970650d90e45",
"dc5859dd5163c4354d5d577b855fa98e37f04384",
"4c17926feb6e87f5bca7890d8a5cde744f231dab"];
// ok. let's loop.
var sha1:SHA1 = new SHA1;
for (var i:uint=0;i<srcs.length;i++) {
var src:ByteArray = Hex.toArray(srcs[i]);
var digest:ByteArray = sha1.hash(src);
assert("SHA1 Long Test "+i, Hex.fromArray(digest) == hashes[i]);
}
}
}
}

View file

@ -1,58 +0,0 @@
/**
* SHA224Test
*
* A test class for SHA224
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import com.hurlant.crypto.hash.SHA224;
import com.hurlant.util.Hex;
import flash.utils.ByteArray;
public class SHA224Test extends TestCase
{
public function SHA224Test(h:ITestHarness)
{
super(h,"SHA-224 Test");
runTest(testSha224,"SHA-224 Test Vectors");
// takes a few seconds, but uncomment if you must.
//runTest(testLongSha224,"SHA-224 Long Test Vectors");
h.endTestCase();
}
/**
* Test vectors courtesy of
* http://www.ietf.org/rfc/rfc3874.txt
*/
public function testSha224():void {
var srcs:Array = [
Hex.fromString("abc"),
Hex.fromString("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")];
var hashes:Array = [
"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7",
"75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525"];
var sha224:SHA224 = new SHA224;
for (var i:uint=0;i<srcs.length;i++) {
var src:ByteArray = Hex.toArray(srcs[i]);
var digest:ByteArray = sha224.hash(src);
assert("SHA224 Test "+i, Hex.fromArray(digest) == hashes[i]);
}
}
public function testLongSha224():void {
var src:ByteArray = new ByteArray;
var a:uint = "a".charCodeAt(0);
for (var i:uint=0;i<1e6;i++) {
src[i] = a;
}
var sha224:SHA224 = new SHA224;
var digest:ByteArray = sha224.hash(src);
var hash:String = "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67";
assert("SHA224 Long Test", Hex.fromArray(digest) == hash);
}
}
}

View file

@ -1,60 +0,0 @@
/**
* SHA256Test
*
* A test class for SHA256
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import com.hurlant.crypto.hash.SHA256;
import com.hurlant.util.Hex;
import flash.utils.ByteArray;
public class SHA256Test extends TestCase
{
public function SHA256Test(h:ITestHarness)
{
super(h,"SHA-256 Test");
runTest(testSha256,"SHA-256 Test Vectors");
h.endTestCase();
}
/**
* Test vectors courtesy of
* https://www.cosic.esat.kuleuven.be/nessie/testvectors/hash/sha/Sha-2-256.unverified.test-vectors
*/
public function testSha256():void {
var srcs:Array = [
Hex.fromString(""),
Hex.fromString("a"),
Hex.fromString("abc"),
Hex.fromString("message digest"),
Hex.fromString("abcdefghijklmnopqrstuvwxyz"),
Hex.fromString("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"),
Hex.fromString("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"),
Hex.fromString("12345678901234567890123456789012345678901234567890123456789012345678901234567890"),
];
var hashes:Array = [
"E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
"CA978112CA1BBDCAFAC231B39A23DC4DA786EFF8147C4E72B9807785AFEE48BB",
"BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD",
"F7846F55CF23E14EEBEAB5B4E1550CAD5B509E3348FBC4EFA3A1413D393CB650",
"71C480DF93D6AE2F1EFAD1447C66C9525E316218CF51FC8D9ED832F2DAF18B73",
"248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1",
"DB4BFCBD4DA0CD85A60C3C37D3FBD8805C77F15FC6B1FDFE614EE0A7C8FDB4C0",
"F371BC4A311F2B009EEF952DD83CA80E2B60026C8E935592D0F9C308453C813E"];
// loop.
var sha256:SHA256 = new SHA256;
for (var i:uint=0;i<srcs.length;i++) {
var src:ByteArray = Hex.toArray(srcs[i]);
var digest:ByteArray = sha256.hash(src);
assert("SHA256 Test "+i, Hex.fromArray(digest) == hashes[i].toLowerCase());
}
}
}
}

View file

@ -1,51 +0,0 @@
/**
* TLSPRFTest
*
* A test class for TLFPRF
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
import flash.utils.ByteArray;
import com.hurlant.crypto.prng.TLSPRF;
import com.hurlant.util.Hex;
public class TLSPRFTest extends TestCase
{
public function TLSPRFTest(h:ITestHarness) {
super(h, "TLS-PRF Testing");
runTest(testVector, "TLF-PRF Test Vector");
h.endTestCase()
}
/**
* Test Vector as defined in
* http://www.imc.org/ietf-tls/mail-archive/msg01589.html
*/
private function testVector():void {
var secret:ByteArray = new ByteArray;
for (var i:uint=0;i<48;i++) {
secret[i]= 0xab;
}
var label:String = "PRF Testvector";
var seed:ByteArray = new ByteArray;
for (i=0;i<64;i++) {
seed[i] = 0xcd;
}
var prf:TLSPRF = new TLSPRF(secret, label, seed);
var out:ByteArray = new ByteArray;
prf.nextBytes(out, 104);
var expected:String = "D3 D4 D1 E3 49 B5 D5 15 04 46 66 D5 1D E3 2B AB" +
"25 8C B5 21 B6 B0 53 46 3E 35 48 32 FD 97 67 54" +
"44 3B CF 9A 29 65 19 BC 28 9A BC BC 11 87 E4 EB" +
"D3 1E 60 23 53 77 6C 40 8A AF B7 4C BC 85 EF F6" +
"92 55 F9 78 8F AA 18 4C BB 95 7A 98 19 D8 4A 5D" +
"7E B0 06 EB 45 9D 3A E8 DE 98 10 45 4B 8B 2D 8F" +
"1A FB C6 55 A8 C9 A0 13";
var expect:String = Hex.fromArray(Hex.toArray(expected));
assert("out == expected", Hex.fromArray(out)==expect);
}
}
}

View file

@ -1,42 +0,0 @@
/**
* TestCase
*
* Embryonic unit test support class.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.crypto.tests
{
public class TestCase
{
public var harness:ITestHarness;
public function TestCase(h:ITestHarness, title:String) {
harness = h;
harness.beginTestCase(title);
}
public function assert(msg:String, value:Boolean):void {
if (value) {
// TestHarness.print("+ ",msg);
return;
}
throw new Error("Test Failure:"+msg);
}
public function runTest(f:Function, title:String):void {
harness.beginTest(title);
try {
f();
} catch (e:Error) {
trace("EXCEPTION THROWN: "+e);
trace(e.getStackTrace());
harness.failTest(e.toString());
return;
}
harness.passTest();
}
}
}

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