commit 2e423d95174cf2918be68b2eb8c8673a5bce111e
Author: Mike Hamburg
Date: Wed May 26 15:34:42 2010 -0700
initial commit for GitHub
diff --git a/README/COPYRIGHT b/README/COPYRIGHT
new file mode 100644
index 00000000..d573a057
--- /dev/null
+++ b/README/COPYRIGHT
@@ -0,0 +1,32 @@
+SJCL used to be in the public domain. Now it's:
+
+Copyright 2009-2010 Emily Stark, Mike Hamburg, Dan Boneh, Stanford University.
+
+This is for liability reasons. (Speaking of which, SJCL comes with NO
+WARRANTY WHATSOEVER, express or implied, to the limit of applicable
+law.)
+
+SJCL is dual-licensed under the GNU GPL version 2.0 or higher, and a
+2-clause BSD license. You may use SJCL under the terms of either of
+these licenses. For your convenience, the GPL versions 2.0 and 3.0
+and the 2-clause BSD license are included here. Additionally, you may
+serve "crunched" copies of sjcl (i.e. those with comments removed,
+and other transformations to reduce code size) without any copyright
+notice.
+
+SJCL includes JsDoc toolkit, YUI compressor, Closure compressor,
+JSLint and the CodeView template in its build system. These programs'
+copyrights are owned by other people. They are distributed here under
+the MPL, MIT, BSD, Apache and JSLint licenses. Codeview is "free for
+download" but has no license attached; it is Copyright 2010 Wouter Bos.
+
+The BSD license is (almost?) strictly more permissive, but the
+additionally licensing under the GPL allows us to use OCB 2.0 code
+royalty-free (at least, if OCB 2.0's creator Phil Rogaway has anything
+to say about it). Note that if you redistribute SJCL under a license
+other than the GPL, you or your users may need to pay patent licensing
+fees for OCB 2.0.
+
+There may be patents which apply to SJCL other than Phil Rogaway's OCB
+patents. We suggest that you consult legal counsel before using SJCL
+in a commercial project.
diff --git a/README/INSTALL b/README/INSTALL
new file mode 100644
index 00000000..a5898c40
--- /dev/null
+++ b/README/INSTALL
@@ -0,0 +1,36 @@
+SJCL comes with a file sjcl.js pre-built. This default build includes
+all the modules except for sjcl.codec.bytes (because the demo site doesn't
+use it). All you need to do to install is copy this file to your web
+server and start using it.
+
+SJCL is divided into modules implementing various cryptographic and
+convenience functions. If you don't need them all for your application,
+you can reconfigure SJCL for a smaller code size. To do this, you can
+run
+
+./configure --without-all --with-aes --with-sha256 ...
+
+Then type
+
+make
+
+to rebuild sjcl.js. This will also create a few intermediate files
+core*.js; you can delete these automatically by typing
+
+make sjcl.js tidy
+
+instead. You will need make, perl, bash and java to rebuild SJCL.
+
+Some of the modules depend on other modules; configure should handle this
+automatically unless you tell it --without-FOO --with-BAR, where BAR
+depends on FOO. If you do this, configure will yell at you.
+
+SJCL is compressed by stripping comments, shortening variable names, etc.
+You can also pass a --compress argument to configure to change the
+compressor. By default SJCL uses some perl/sh scripts and Google's
+Closure compressor.
+
+If you reconfigure SJCL, it is recommended that you run the included test
+suite by typing "make test". If this prints "FAIL" or segfaults, SJCL
+doesn't work; please file a bug.
+
diff --git a/README/bsd.txt b/README/bsd.txt
new file mode 100644
index 00000000..a0559ed0
--- /dev/null
+++ b/README/bsd.txt
@@ -0,0 +1,30 @@
+Copyright 2009-2010 Emily Stark, Mike Hamburg, Dan Boneh.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS 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 SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The views and conclusions contained in the software and documentation
+are those of the authors and should not be interpreted as representing
+official policies, either expressed or implied, of the authors.
diff --git a/README/gpl-2.0.txt b/README/gpl-2.0.txt
new file mode 100644
index 00000000..d159169d
--- /dev/null
+++ b/README/gpl-2.0.txt
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ , 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/README/gpl-3.0.txt b/README/gpl-3.0.txt
new file mode 100644
index 00000000..94a9ed02
--- /dev/null
+++ b/README/gpl-3.0.txt
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/browserTest/browserTest.html b/browserTest/browserTest.html
new file mode 100644
index 00000000..be8d5348
--- /dev/null
+++ b/browserTest/browserTest.html
@@ -0,0 +1,16 @@
+
+
+
+
+ SJCL browser test
+
+
+
+
+
+
SJCL browser test
+
Waiting for tests to begin...
+
+
+
diff --git a/browserTest/browserUtil.js b/browserTest/browserUtil.js
new file mode 100644
index 00000000..3b2fc99d
--- /dev/null
+++ b/browserTest/browserUtil.js
@@ -0,0 +1,128 @@
+browserUtil = {};
+
+browserUtil.isRhino = (typeof(window) === 'undefined');
+
+/**
+ * Pause (for the graphics to update and the script timer to clear), then run the
+ * specified action.
+ */
+browserUtil.pauseAndThen = function (cb) {
+ cb && window.setTimeout(cb, 1);
+};
+
+/**
+ * Iterate using continuation-passing style.
+ */
+browserUtil.cpsIterate = function (f, start, end, pause, callback) {
+ var pat = pause ? browserUtil.pauseAndThen : function (cb) { cb && cb(); };
+ function go() {
+ var called = false;
+ if (start >= end) {
+ pat(callback);
+ } else {
+ pat(function () { f(start, function () {
+ if (!called) { called = true; start++; go(); }
+ }); });
+ }
+ }
+ go (start);
+};
+
+/**
+ * Map a function over an array using continuation-passing style.
+ */
+browserUtil.cpsMap = function (map, list, pause, callback) {
+ browserUtil.cpsIterate(function (i, cb) { map(list[i], i, list.length, cb); },
+ 0, list.length, pause, callback);
+}
+
+/** Cache for remotely loaded scripts. */
+browserUtil.scriptCache = {}
+
+/** Load several scripts, then call back */
+browserUtil.loadScripts = function(scriptNames, cbSuccess, cbError) {
+ var head = document.getElementsByTagName('head')[0];
+ browserUtil.cpsMap(function (script, i, n, cb) {
+ var scriptE = document.createElement('script'), xhr, loaded = false;
+
+ browserUtil.status("Loading script " + script);
+
+ if (window.location.protocol === "file:") {
+ /* Can't make an AJAX request for files.
+ * But, we know the load time will be short, so timeout-based error
+ * detection is fine.
+ */
+ scriptE.onload = function () {
+ loaded = true;
+ cb();
+ };
+ scriptE.onerror = function(err) {
+ cbError && cbError(script, err, cb);
+ };
+ script.onreadystatechange = function() {
+ if (this.readyState == 'complete' || this.readyState == 'loaded') {
+ loaded = true;
+ cb();
+ }
+ };
+ scriptE.type = 'text/javascript';
+ scriptE.src = script+"?"+(new Date().valueOf());
+ window.setTimeout(function () {
+ loaded || cbError && cbError(script, "timeout expired", cb);
+ }, 100);
+ head.appendChild(scriptE);
+ } else if (browserUtil.scriptCache[script] !== undefined) {
+ try {
+ scriptE.appendChild(document.createTextNode(browserUtil.scriptCache[script]));
+ } catch (e) {
+ scriptE.text = browserUtil.scriptCache[script];
+ }
+ head.appendChild(scriptE);
+ cb();
+ } else {
+ var xhr = new XMLHttpRequest();
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState == 4) {
+ if (xhr.status == 200) {
+ browserUtil.scriptCache[script] = xhr.responseText;
+ try {
+ scriptE.appendChild(document.createTextNode(xhr.responseText));
+ } catch (e) {
+ scriptE.text = xhr.responseText;
+ }
+ head.appendChild(scriptE);
+ cb();
+ } else {
+ cbError && cbError(script, xhr.status, cb);
+ }
+ }
+ }
+ xhr.open("GET", script+"?"+(new Date().valueOf()), true);
+ xhr.send();
+ }
+ }, scriptNames, false, cbSuccess);
+};
+
+/** Write a message to the console */
+browserUtil.write = function(type, message) {
+ var d1 = document.getElementById("print"), d2 = document.createElement("div"), d3 = document.createElement("div");
+ d3.className = type;
+ d3.appendChild(document.createTextNode(message));
+ d2.appendChild(d3);
+ d1.appendChild(d2);
+ return { update: function (type2, message2) {
+ var d4 = document.createElement("div");
+ d4.className = type2 + " also";
+ d4.appendChild(document.createTextNode(message2));
+ d2.insertBefore(d4, d3);
+ }};
+};
+
+/** Write a newline. Does nothing in the browser. */
+browserUtil.writeNewline = function () { };
+
+/** Write a message to the status line */
+browserUtil.status = function(message) {
+ var d1 = document.getElementById("status");
+ d1.replaceChild(document.createTextNode(message), d1.firstChild);
+};
diff --git a/browserTest/rhinoUtil.js b/browserTest/rhinoUtil.js
new file mode 100644
index 00000000..3107104d
--- /dev/null
+++ b/browserTest/rhinoUtil.js
@@ -0,0 +1,44 @@
+browserUtil = {
+ isRhino: true,
+
+ pauseAndThen: function (cb) { cb(); },
+
+ cpsIterate: function (f, start, end, pause, callback) {
+ function go() {
+ var called = false;
+ if (start >= end) {
+ callback && callback();
+ } else {
+ f(start, function () {
+ if (!called) { called = true; start++; go(); }
+ });
+ }
+ }
+ go (start);
+ },
+
+ cpsMap: function (map, list, pause, callback) {
+ browserUtil.cpsIterate(function (i, cb) { map(list[i], i, list.length, cb); },
+ 0, list.length, pause, callback);
+ },
+
+ loadScripts: function(scriptNames, callback) {
+ for (i=0; i .begin, *+* > .all {
+ margin-top: 1em;
+}
+
+.also {
+ float: right;
+ width: 17em;
+ text-align: right;
+}
+
+h1 {
+ text-align: center;
+ background: #8A0000;
+ padding: 5px;
+ color: white;
+}
+
+#status {
+ padding: 3px 10px 3px 5px;
+ background: #d5c490;
+ color: #444;
+ font-size: 0.8em;
+ margin-bottom: 1em;
+ height: 1.3em;
+ vertical-align: middle;
+}
diff --git a/compress/compiler.jar b/compress/compiler.jar
new file mode 100644
index 00000000..c087e922
Binary files /dev/null and b/compress/compiler.jar differ
diff --git a/compress/compress_with_closure.sh b/compress/compress_with_closure.sh
new file mode 100755
index 00000000..07985c87
--- /dev/null
+++ b/compress/compress_with_closure.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+DIR=`dirname $0`
+
+$DIR/remove_constants.pl $1 | $DIR/opacify.pl > ._tmpRC.js
+
+echo -n '"use strict";'
+java -jar $DIR/compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS \
+ --js ._tmpRC.js \
+ | $DIR/digitize.pl \
+ | $DIR/dewindowize.pl
+
+
+rm -f ._tmpRC.js
+
diff --git a/compress/compress_with_yui.sh b/compress/compress_with_yui.sh
new file mode 100755
index 00000000..9dfecdac
--- /dev/null
+++ b/compress/compress_with_yui.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# Compress $1 with YUI Compressor 2.4.2, returning the compressed script on stdout
+
+DIR=`dirname $0`
+
+$DIR/remove_constants.pl $1 > ._tmpRC.js
+
+java -jar $DIR/yuicompressor-2.4.2.jar ._tmpRC.js \
+ | $DIR/digitize.pl
+
+rm -f ._tmpRC.js
+
diff --git a/compress/dewindowize.pl b/compress/dewindowize.pl
new file mode 100755
index 00000000..c8843825
--- /dev/null
+++ b/compress/dewindowize.pl
@@ -0,0 +1,8 @@
+#!/usr/bin/env perl
+
+while (<>) {
+ s/window\.sjcl\s*=/var sjcl=/g;
+ s/window\.sjcl/sjcl/g;
+ print;
+}
+
diff --git a/compress/digitize.pl b/compress/digitize.pl
new file mode 100755
index 00000000..98db16af
--- /dev/null
+++ b/compress/digitize.pl
@@ -0,0 +1,22 @@
+#!/usr/bin/env perl
+
+# Convert numbers to hex, when doing so is likely to increase compressibility.
+# This actually makes the script slightly longer, but generally makes it compress
+# to something shorter.
+#
+# Here we're targeting constants like 0xFF, 0xFFFF0000, 0x10101, 0x100000000, etc.
+
+sub digitize {
+ my $number = shift;
+ if ($number >= 256) {
+ my $nn = sprintf("%x", $number);
+ if ($nn =~ /^[01f]+$/i) { return "0x$nn"; }
+ }
+ return $number;
+}
+
+while (<>) {
+ s/([^a-zA-Z0-9_])(\d+)/$1 . digitize $2/eg;
+ print;
+}
+
diff --git a/compress/opacify.pl b/compress/opacify.pl
new file mode 100755
index 00000000..d17c914b
--- /dev/null
+++ b/compress/opacify.pl
@@ -0,0 +1,32 @@
+#!/usr/bin/env perl
+
+# This script is a hack.
+#
+# Opacify all non-private names by turning them into strings.
+# That way, the Google compressor won't rename them.
+#
+# The script ignores properties whose names begin with _, because they
+# are believed to be private.
+#
+# XXX TODO FIXME: this messes with strings, so it screws up exceptions.
+
+my $script = join '', <>;
+
+# remove comments
+$script =~ s=/\*([^\*]|\*+[^\/])*\*/==g;
+$script =~ s=//.*==g;
+
+# stringify property names
+$script =~ s=\.([a-zA-Z0-9][_a-zA-Z0-9]*)=['$1']=g;
+
+# stringify sjcl
+$script =~ s=(?:var\s+)?sjcl(\.|\s*\=)=window['sjcl']$1=g;
+
+# stringify object notation
+$script =~ s=([\{,]\s*)([a-zA-Z0-9][_a-zA-Z0-9]*):=$1'$2':=g;
+
+# Export sjcl. This is a bit of a hack, and might get replaced later.
+print $script;
+
+# not necessary with windowization.
+# print "window\['sjcl'\] = sjcl;\n";
diff --git a/compress/remove_constants.pl b/compress/remove_constants.pl
new file mode 100755
index 00000000..c9b0f22d
--- /dev/null
+++ b/compress/remove_constants.pl
@@ -0,0 +1,69 @@
+#!/usr/bin/env perl
+
+# This script is a hack. It identifies things which it believes to be
+# constant, then replaces them throughout the code.
+#
+# Constants are identified as properties declared in object notation
+# with values consisting only of capital letters and underscores. If
+# the first character is an underscore, the constant is private, and
+# can be removed entirely.
+#
+# The script dies if any two constants have the same property name but
+# different values.
+my $script = join '', <>;
+
+# remove comments
+$script =~ s=/\*([^\*]|\*+[^\/])*\*/==g;
+$script =~ s=//.*==g;
+
+sub preserve {
+ my $stuff = shift;
+ $stuff =~ s/,//;
+ return $stuff;
+}
+
+my %constants = ();
+
+sub add_constant {
+ my ($name, $value) = @_;
+ if (defined $constants{$name} && $constants{$name} ne $value) {
+ print STDERR "variant constant $name = $value";
+ die;
+ } else {
+ $constants{$name} = $value;
+ #print STDERR "constant: $name = $value\n";
+ }
+}
+
+# find private constants
+while ($script =~
+ s/([,\{]) \s* # indicator that this is part of an object
+ (_[A-Z0-9_]+) \s* : \s* # all-caps variable name beginning with _
+ (\d+|0x[0-9A-Fa-f]+) \s* # numeric value
+ ([,\}]) # next part of object
+ /preserve "$1$4"/ex) {
+ add_constant $2, $3;
+}
+
+my $script2 = '';
+
+# find public constants
+while ($script =~
+ s/^(.*?) # beginning of script
+ ([,\{]) \s* # indicator that this is part of an object
+ ([A-Z0-9_]+) \s* : \s* # all-caps variable name
+ (\d+|0x[0-9A-Fa-f]+) \s* # numeric value
+ ([,\}]) # next part of object([,\{]) \s*
+ /$5/esx) {
+ $script2 .= "$1$2$3:$4";
+ add_constant $3, $4;
+}
+
+$script = "$script2$script";
+
+foreach (keys %constants) {
+ my $value = $constants{$_};
+ $script =~ s/(?:[a-zA-Z0-9_]+\.)+$_(?=[^a-zA-Z0-9_])/$value/g;
+}
+
+print $script;
diff --git a/compress/yuicompressor-2.4.2.jar b/compress/yuicompressor-2.4.2.jar
new file mode 100644
index 00000000..c29470bd
Binary files /dev/null and b/compress/yuicompressor-2.4.2.jar differ
diff --git a/core/aes.js b/core/aes.js
new file mode 100644
index 00000000..144cd248
--- /dev/null
+++ b/core/aes.js
@@ -0,0 +1,208 @@
+/** @fileOverview Low-level AES implementation.
+ *
+ * This file contains a low-level implementation of AES, optimized for
+ * size and for efficiency on several browsers. It is based on
+ * OpenSSL's aes_core.c, a public-domain implementation by Vincent
+ * Rijmen, Antoon Bosselaers and Paulo Barreto.
+ *
+ * An older version of this implementation is available in the public
+ * domain, but this one is (c) Emily Stark, Mike Hamburg, Dan Boneh,
+ * Stanford University 2008-2010 and BSD-licensed for liability
+ * reasons.
+ *
+ * @author Emily Stark
+ * @author Mike Hamburg
+ * @author Dan Boneh
+ */
+
+/**
+ * Schedule out an AES key for both encryption and decryption. This
+ * is a low-level class. Use a cipher mode to do bulk encryption.
+ *
+ * @constructor
+ * @param {Array} key The key as an array of 4, 6 or 8 words.
+ *
+ * @class Advanced Encryption Standard (low-level interface)
+ */
+sjcl.cipher.aes = function (key) {
+ if (!this._tables[0][0][0]) {
+ this._precompute();
+ }
+
+ var i, j, tmp,
+ encKey, decKey,
+ sbox = this._tables[0][4], decTable = this._tables[1],
+ keyLen = key.length, rcon = 1;
+
+ if (keyLen !== 4 && keyLen !== 6 && keyLen !== 8) {
+ throw new sjcl.exception.invalid("invalid aes key size");
+ }
+
+ this._key = [encKey = key.slice(0), decKey = []];
+
+ // schedule encryption keys
+ for (i = keyLen; i < 4 * keyLen + 28; i++) {
+ tmp = encKey[i-1];
+
+ // apply sbox
+ if (i%keyLen === 0 || (keyLen === 8 && i%keyLen === 4)) {
+ tmp = sbox[tmp>>>24]<<24 ^ sbox[tmp>>16&255]<<16 ^ sbox[tmp>>8&255]<<8 ^ sbox[tmp&255];
+
+ // shift rows and add rcon
+ if (i%keyLen === 0) {
+ tmp = tmp<<8 ^ tmp>>>24 ^ rcon<<24;
+ rcon = rcon<<1 ^ (rcon>>7)*283;
+ }
+ }
+
+ encKey[i] = encKey[i-keyLen] ^ tmp;
+ }
+
+ // schedule decryption keys
+ for (j = 0; i; j++, i--) {
+ tmp = encKey[j&3 ? i : i - 4];
+ if (i<=4 || j<4) {
+ decKey[j] = tmp;
+ } else {
+ decKey[j] = decTable[0][sbox[tmp>>>24 ]] ^
+ decTable[1][sbox[tmp>>16 & 255]] ^
+ decTable[2][sbox[tmp>>8 & 255]] ^
+ decTable[3][sbox[tmp & 255]];
+ }
+ }
+};
+
+sjcl.cipher.aes.prototype = {
+ // public
+ /* Something like this might appear here eventually
+ name: "AES",
+ blockSize: 4,
+ keySizes: [4,6,8],
+ */
+
+ /**
+ * Encrypt an array of 4 big-endian words.
+ * @param {Array} data The plaintext.
+ * @return {Array} The ciphertext.
+ */
+ encrypt:function (data) { return this._crypt(data,0); },
+
+ /**
+ * Decrypt an array of 4 big-endian words.
+ * @param {Array} data The ciphertext.
+ * @return {Array} The plaintext.
+ */
+ decrypt:function (data) { return this._crypt(data,1); },
+
+ /**
+ * The expanded S-box and inverse S-box tables. These will be computed
+ * on the client so that we don't have to send them down the wire.
+ *
+ * There are two tables, _tables[0] is for encryption and
+ * _tables[1] is for decryption.
+ *
+ * The first 4 sub-tables are the expanded S-box with MixColumns. The
+ * last (_tables[01][4]) is the S-box itself.
+ *
+ * @private
+ */
+ _tables: [[[],[],[],[],[]],[[],[],[],[],[]]],
+
+ /**
+ * Expand the S-box tables.
+ *
+ * @private
+ */
+ _precompute: function () {
+ var encTable = this._tables[0], decTable = this._tables[1],
+ sbox = encTable[4], sboxInv = decTable[4],
+ i, x, xInv, d=[], th=[], x2, x4, x8, s, tEnc, tDec;
+
+ // Compute double and third tables
+ for (i = 0; i < 256; i++) {
+ th[( d[i] = i<<1 ^ (i>>7)*283 )^i]=i;
+ }
+
+ for (x = xInv = 0; !sbox[x]; x ^= x2 || 1, xInv = th[xInv] || 1) {
+ // Compute sbox
+ s = xInv ^ xInv<<1 ^ xInv<<2 ^ xInv<<3 ^ xInv<<4;
+ s = s>>8 ^ s&255 ^ 99;
+ sbox[x] = s;
+ sboxInv[s] = x;
+
+ // Compute MixColumns
+ x8 = d[x4 = d[x2 = d[x]]];
+ tDec = x8*0x1010101 ^ x4*0x10001 ^ x2*0x101 ^ x*0x1010100;
+ tEnc = d[s]*0x101 ^ s*0x1010100;
+
+ for (i = 0; i < 4; i++) {
+ encTable[i][x] = tEnc = tEnc<<24 ^ tEnc>>>8;
+ decTable[i][s] = tDec = tDec<<24 ^ tDec>>>8;
+ }
+ }
+
+ // Compactify. Considerable speedup on Firefox.
+ for (i = 0; i < 5; i++) {
+ encTable[i] = encTable[i].slice(0);
+ decTable[i] = decTable[i].slice(0);
+ }
+ },
+
+ /**
+ * Encryption and decryption core.
+ * @param {Array} input Four words to be encrypted or decrypted.
+ * @param dir The direction, 0 for encrypt and 1 for decrypt.
+ * @return {Array} The four encrypted or decrypted words.
+ * @private
+ */
+ _crypt:function (input, dir) {
+ if (input.length !== 4) {
+ throw new sjcl.exception.invalid("invalid aes block size");
+ }
+
+ var key = this._key[dir],
+ // state variables a,b,c,d are loaded with pre-whitened data
+ a = input[0] ^ key[0],
+ b = input[dir ? 3 : 1] ^ key[1],
+ c = input[2] ^ key[2],
+ d = input[dir ? 1 : 3] ^ key[3],
+ a2, b2, c2,
+
+ nInnerRounds = key.length/4 - 2,
+ i,
+ kIndex = 4,
+ out = [0,0,0,0],
+ table = this._tables[dir],
+
+ // load up the tables
+ t0 = table[0],
+ t1 = table[1],
+ t2 = table[2],
+ t3 = table[3],
+ sbox = table[4];
+
+ // Inner rounds. Cribbed from OpenSSL.
+ for (i = 0; i < nInnerRounds; i++) {
+ a2 = t0[a>>>24] ^ t1[b>>16 & 255] ^ t2[c>>8 & 255] ^ t3[d & 255] ^ key[kIndex];
+ b2 = t0[b>>>24] ^ t1[c>>16 & 255] ^ t2[d>>8 & 255] ^ t3[a & 255] ^ key[kIndex + 1];
+ c2 = t0[c>>>24] ^ t1[d>>16 & 255] ^ t2[a>>8 & 255] ^ t3[b & 255] ^ key[kIndex + 2];
+ d = t0[d>>>24] ^ t1[a>>16 & 255] ^ t2[b>>8 & 255] ^ t3[c & 255] ^ key[kIndex + 3];
+ kIndex += 4;
+ a=a2; b=b2; c=c2;
+ }
+
+ // Last round.
+ for (i = 0; i < 4; i++) {
+ out[dir ? 3&-i : i] =
+ sbox[a>>>24 ]<<24 ^
+ sbox[b>>16 & 255]<<16 ^
+ sbox[c>>8 & 255]<<8 ^
+ sbox[d & 255] ^
+ key[kIndex++];
+ a2=a; a=b; b=c; c=d; d=a2;
+ }
+
+ return out;
+ }
+};
+
diff --git a/core/bitArray.js b/core/bitArray.js
new file mode 100644
index 00000000..40e4acd0
--- /dev/null
+++ b/core/bitArray.js
@@ -0,0 +1,166 @@
+/** @fileOverview Arrays of bits, encoded as arrays of Numbers.
+ *
+ * @author Emily Stark
+ * @author Mike Hamburg
+ * @author Dan Boneh
+ */
+
+/** @namespace Arrays of bits, encoded as arrays of Numbers.
+ *
+ * @description
+ *
+ * These objects are the currency accepted by SJCL's crypto functions.
+ *
+ *
+ *
+ * Most of our crypto primitives operate on arrays of 4-byte words internally,
+ * but many of them can take arguments that are not a multiple of 4 bytes.
+ * This library encodes arrays of bits (whose size need not be a multiple of 8
+ * bits) as arrays of 32-bit words. The bits are packed, big-endian, into an
+ * array of words, 32 bits at a time. Since the words are double-precision
+ * floating point numbers, they fit some extra data. We use this (in a private,
+ * possibly-changing manner) to encode the number of bits actually present
+ * in the last word of the array.
+ *
+ *
+ *
+ * Because bitwise ops clear this out-of-band data, these arrays can be passed
+ * to ciphers like AES which want arrays of words.
+ *
+ */
+sjcl.bitArray = {
+ /**
+ * Array slices in units of bits.
+ * @param {bitArray a} The array to slice.
+ * @param {Number} bstart The offset to the start of the slice, in bits.
+ * @param {Number} bend The offset to the end of the slice, in bits. If this is undefined,
+ * slice until the end of the array.
+ * @return {bitArray} The requested slice.
+ */
+ bitSlice: function (a, bstart, bend) {
+ a = sjcl.bitArray._shiftRight(a.slice(bstart/32), 32 - (bstart & 31)).slice(1);
+ return (bend === undefined) ? a : sjcl.bitArray.clamp(a, bend-bstart);
+ },
+
+ /**
+ * Concatenate two bit arrays.
+ * @param {bitArray} a1 The first array.
+ * @param {bitArray} a2 The second array.
+ * @return {bitArray} The concatenation of a1 and a2.
+ */
+ concat: function (a1, a2) {
+ if (a1.length === 0 || a2.length === 0) {
+ return a1.concat(a2);
+ }
+
+ var out, i, last = a1[a1.length-1], shift = sjcl.bitArray.getPartial(last);
+ if (shift === 32) {
+ return a1.concat(a2);
+ } else {
+ return sjcl.bitArray._shiftRight(a2, shift, last|0, a1.slice(0,a1.length-1));
+ }
+ },
+
+ /**
+ * Find the length of an array of bits.
+ * @param {bitArray} a The array.
+ * @return {Number} The length of a, in bits.
+ */
+ bitLength: function (a) {
+ var l = a.length, x;
+ if (l === 0) { return 0; }
+ x = a[l - 1];
+ return (l-1) * 32 + sjcl.bitArray.getPartial(x);
+ },
+
+ /**
+ * Truncate an array.
+ * @param {bitArray} a The array.
+ * @param {Number} len The length to truncate to, in bits.
+ * @return {bitArray} A new array, truncated to len bits.
+ */
+ clamp: function (a, len) {
+ if (a.length * 32 < len) { return a; }
+ a = a.slice(0, Math.ceil(len / 32));
+ var l = a.length;
+ len = len & 31;
+ if (l > 0 && len) {
+ a[l-1] = sjcl.bitArray.partial(len, a[l-1] & 0x80000000 >> (len-1), 1);
+ }
+ return a;
+ },
+
+ /**
+ * Make a partial word for a bit array.
+ * @param {Number} len The number of bits in the word.
+ * @param {Number} x The bits.
+ * @param {Number} [0] _end Pass 1 if x has already been shifted to the high side.
+ * @return {Number} The partial word.
+ */
+ partial: function (len, x, _end) {
+ if (len === 32) { return x; }
+ return (_end ? x|0 : x << (32-len)) + len * 0x10000000000;
+ },
+
+ /**
+ * Get the number of bits used by a partial word.
+ * @param {Number} x The partial word.
+ * @return {Number} The number of bits used by the partial word.
+ */
+ getPartial: function (x) {
+ return Math.round(x/0x10000000000) || 32;
+ },
+
+ /**
+ * Compare two arrays for equality in a predictable amount of time.
+ * @param {bitArray} a The first array.
+ * @param {bitArray} b The second array.
+ * @return {boolean} true if a == b; false otherwise.
+ */
+ equal: function (a, b) {
+ if (sjcl.bitArray.bitLength(a) !== sjcl.bitArray.bitLength(b)) {
+ return false;
+ }
+ var x = 0, i;
+ for (i=0; i= 32; shift -= 32) {
+ out.push(carry);
+ carry = 0;
+ }
+ if (shift === 0) {
+ return out.concat(a);
+ }
+
+ for (i=0; i>>shift);
+ carry = a[i] << (32-shift);
+ }
+ last2 = a.length ? a[a.length-1] : 0;
+ shift2 = sjcl.bitArray.getPartial(last2);
+ out.push(sjcl.bitArray.partial(shift+shift2 & 31, (shift + shift2 > 32) ? carry : out.pop(),1));
+ return out;
+ },
+
+ /** xor a block of 4 words together.
+ * @private
+ */
+ _xor4: function(x,y) {
+ return [x[0]^y[0],x[1]^y[1],x[2]^y[2],x[3]^y[3]];
+ }
+};
diff --git a/core/ccm.js b/core/ccm.js
new file mode 100644
index 00000000..c51db006
--- /dev/null
+++ b/core/ccm.js
@@ -0,0 +1,185 @@
+/** @fileOverview CCM mode implementation.
+ *
+ * Special thanks to Roy Nicholson for pointing out a bug in our
+ * implementation.
+ *
+ * @author Emily Stark
+ * @author Mike Hamburg
+ * @author Dan Boneh
+ */
+
+/** @namespace CTR mode with CBC MAC. */
+sjcl.mode.ccm = {
+ /** The name of the mode.
+ * @constant
+ */
+ name: "ccm",
+
+ /** Encrypt in CCM mode.
+ * @static
+ * @param {Object} prf The pseudorandom function. It must have a block size of 16 bytes.
+ * @param {bitArray} plaintext The plaintext data.
+ * @param {bitArray} iv The initialization value.
+ * @param {bitArray} [adata=[]] The authenticated data.
+ * @param {Number} [tlen=64] the desired tag length, in bits.
+ * @return {bitArray} The encrypted data, an array of bytes.
+ */
+ encrypt: function(prf, plaintext, iv, adata, tlen) {
+ var L, i, out = plaintext.slice(0), tag, w=sjcl.bitArray, ivl = w.bitLength(iv) / 8, ol = w.bitLength(out) / 8;
+ tlen = tlen || 64;
+ adata = adata || [];
+
+ if (ivl < 7) {
+ throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");
+ }
+
+ // compute the length of the length
+ for (L=2; L<4 && ol >>> 8*L; L++) {}
+ if (L < 15 - ivl) { L = 15-ivl; }
+ iv = w.clamp(iv,8*(15-L));
+
+ // compute the tag
+ tag = sjcl.mode.ccm._computeTag(prf, plaintext, iv, adata, tlen, L);
+
+ // encrypt
+ out = sjcl.mode.ccm._ctrMode(prf, out, iv, tag, tlen, L);
+
+ return w.concat(out.data, out.tag);
+ },
+
+ /** Decrypt in CCM mode.
+ * @static
+ * @param {Object} prf The pseudorandom function. It must have a block size of 16 bytes.
+ * @param {bitArray} ciphertext The ciphertext data.
+ * @param {bitArray} iv The initialization value.
+ * @param {bitArray} [[]] adata The authenticated data.
+ * @param {Number} [64] tlen the desired tag length, in bits.
+ * @return {bitArray} The decrypted data.
+ */
+ decrypt: function(prf, ciphertext, iv, adata, tlen) {
+ tlen = tlen || 64;
+ adata = adata || [];
+ var L, i,
+ w=sjcl.bitArray,
+ ivl = w.bitLength(iv) / 8,
+ ol = w.bitLength(ciphertext),
+ out = w.clamp(ciphertext, ol - tlen),
+ tag = w.bitSlice(ciphertext, ol - tlen), tag2;
+
+
+ ol = (ol - tlen) / 8;
+
+ if (ivl < 7) {
+ throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");
+ }
+
+ // compute the length of the length
+ for (L=2; L<4 && ol >>> 8*L; L++) {}
+ if (L < 15 - ivl) { L = 15-ivl; }
+ iv = w.clamp(iv,8*(15-L));
+
+ // decrypt
+ out = sjcl.mode.ccm._ctrMode(prf, out, iv, tag, tlen, L);
+
+ // check the tag
+ tag2 = sjcl.mode.ccm._computeTag(prf, out.data, iv, adata, tlen, L);
+ if (!w.equal(out.tag, tag2)) {
+ throw new sjcl.exception.corrupt("ccm: tag doesn't match");
+ }
+
+ return out.data;
+ },
+
+ /* Compute the (unencrypted) authentication tag, according to the CCM specification
+ * @param {Object} prf The pseudorandom function.
+ * @param {bitArray} plaintext The plaintext data.
+ * @param {bitArray} iv The initialization value.
+ * @param {bitArray} adata The authenticated data.
+ * @param {Number} tlen the desired tag length, in bits.
+ * @return {bitArray} The tag, but not yet encrypted.
+ * @private
+ */
+ _computeTag: function(prf, plaintext, iv, adata, tlen, L) {
+ // compute B[0]
+ var q, mac, field = 0, offset = 24, tmp, i, macData = [], w=sjcl.bitArray, xor = w._xor4;
+
+ tlen /= 8;
+
+ // check tag length and message length
+ if (tlen % 2 || tlen < 4 || tlen > 16) {
+ throw new sjcl.exception.invalid("ccm: invalid tag length");
+ }
+
+ if (adata.length > 0xFFFFFFFF || plaintext.length > 0xFFFFFFFF) {
+ // I don't want to deal with extracting high words from doubles.
+ throw new sjcl.exception.bug("ccm: can't deal with 4GiB or more data");
+ }
+
+ // mac the flags
+ mac = [w.partial(8, (adata.length ? 1<<6 : 0) | (tlen-2) << 2 | L-1)];
+
+ // mac the iv and length
+ mac = w.concat(mac, iv);
+ mac[3] |= w.bitLength(plaintext)/8;
+ mac = prf.encrypt(mac);
+
+
+ if (adata.length) {
+ // mac the associated data. start with its length...
+ tmp = w.bitLength(adata)/8;
+ if (tmp <= 0xFEFF) {
+ macData = [w.partial(16, tmp)];
+ } else if (tmp <= 0xFFFFFFFF) {
+ macData = w.concat([w.partial(16,0xFFFE)], [tmp]);
+ } // else ...
+
+ // mac the data itself
+ macData = w.concat(macData, adata);
+ for (i=0; i>>bits) >>> 26);
+ if (bits < 6) {
+ ta = arr[i] << (6-bits);
+ bits += 26;
+ i++;
+ } else {
+ ta <<= 6;
+ bits -= 6;
+ }
+ }
+ while ((out.length & 3) && !_noEquals) { out += "="; }
+ return out;
+ },
+
+ /** Convert from a base64 string to a bitArray */
+ toBits: function(str) {
+ str = str.replace(/\s|=/g,'');
+ var out = [], i, bits=0, c = sjcl.codec.base64._chars, ta=0, x;
+ for (i=0; i 26) {
+ bits -= 26;
+ out.push(ta ^ x>>>bits);
+ ta = x << (32-bits);
+ } else {
+ bits += 6;
+ ta ^= x << (32-bits);
+ }
+ }
+ if (bits&56) {
+ out.push(sjcl.bitArray.partial(bits&56, ta, 1));
+ }
+ return out;
+ }
+};
diff --git a/core/codecBytes.js b/core/codecBytes.js
new file mode 100644
index 00000000..cde2af3a
--- /dev/null
+++ b/core/codecBytes.js
@@ -0,0 +1,37 @@
+/** @fileOverview Bit array codec implementations.
+ *
+ * @author Emily Stark
+ * @author Mike Hamburg
+ * @author Dan Boneh
+ */
+
+/** @namespace Arrays of bytes */
+sjcl.codec.bytes = {
+ /** Convert from a bitArray to an array of bytes. */
+ fromBits: function (arr) {
+ var out = [], bl = sjcl.bitArray.bitLength(arr), i, tmp;
+ for (i=0; i>> 24);
+ tmp <<= 8;
+ }
+ return out;
+ },
+ /** Convert from an array of bytes to a bitArray. */
+ toBits: function (bytes) {
+ var out = [], i, tmp=0;
+ for (i=0; i>> 24);
+ tmp <<= 8;
+ }
+ return decodeURIComponent(escape(out));
+ },
+
+ /** Convert from a UTF-8 string to a bitArray. */
+ toBits: function (str) {
+ str = unescape(encodeURIComponent(str));
+ var out = [], i, tmp=0;
+ for (i=0; i 4)) {
+ throw new sjcl.exception.invalid("json encrypt: invalid parameters");
+ }
+
+ if (typeof password === "string") {
+ tmp = sjcl.misc.cachedPbkdf2(password, p);
+ password = tmp.key.slice(0,p.ks/32);
+ p.salt = tmp.salt;
+ }
+ if (typeof plaintext === "string") {
+ plaintext = sjcl.codec.utf8String.toBits(plaintext);
+ }
+ prp = new sjcl.cipher[p.cipher](password);
+
+ /* return the json data */
+ j._add(rp, p);
+ rp.key = password;
+
+ /* do the encryption */
+ p.ct = sjcl.mode[p.mode].encrypt(prp, plaintext, p.iv, p.adata, p.tag);
+
+ return j.encode(j._subtract(p, j.defaults));
+ },
+
+ /** Simple decryption function.
+ * @param {String|bitArray} password The password or key.
+ * @param {String} ciphertext The ciphertext to decrypt.
+ * @param {Object} [params] Additional non-default parameters.
+ * @param {Object} [rp] A returned object with filled parameters.
+ * @return {String} The plaintext.
+ * @throws {sjcl.exception.invalid} if a parameter is invalid.
+ * @throws {sjcl.exception.corrupt} if the ciphertext is corrupt.
+ */
+ decrypt: function (password, ciphertext, params, rp) {
+ params = params || {};
+ rp = rp || {};
+
+ var j = sjcl.json, p = j._add(j._add(j._add({},j.defaults),j.decode(ciphertext)), params, true), ct, tmp, prp;
+ if (typeof p.salt === "string") {
+ p.salt = sjcl.codec.base64.toBits(p.salt);
+ }
+ if (typeof p.iv === "string") {
+ p.iv = sjcl.codec.base64.toBits(p.iv);
+ }
+
+ if (!sjcl.mode[p.mode] ||
+ !sjcl.cipher[p.cipher] ||
+ (typeof password === "string" && p.iter <= 100) ||
+ (p.ts !== 64 && p.ts !== 96 && p.ts !== 128) ||
+ (p.ks !== 128 && p.ks !== 192 && p.ks !== 256) ||
+ (!p.iv) ||
+ (p.iv.length < 2 || p.iv.length > 4)) {
+ throw new sjcl.exception.invalid("json decrypt: invalid parameters");
+ }
+
+ if (typeof password === "string") {
+ tmp = sjcl.misc.cachedPbkdf2(password, p);
+ password = tmp.key.slice(0,p.ks/32);
+ p.salt = tmp.salt;
+ }
+ prp = new sjcl.cipher[p.cipher](password);
+
+ /* do the decryption */
+ ct = sjcl.mode[p.mode].decrypt(prp, p.ct, p.iv, p.adata, p.tag);
+
+ /* return the json data */
+ j._add(rp, p);
+ rp.key = password;
+
+ return sjcl.codec.utf8String.fromBits(ct);
+ },
+
+ /** Encode a flat structure into a JSON string.
+ * @param {Object} obj The structure to encode.
+ * @return {String} A JSON string.
+ * @throws {sjcl.exception.invalid} if obj has a non-alphanumeric property.
+ * @throws {sjcl.exception.bug} if a parameter has an unsupported type.
+ */
+ encode: function (obj) {
+ var i, out='{', comma='';
+ for (i in obj) {
+ if (obj.hasOwnProperty(i)) {
+ if (!i.match(/^[a-z0-9]+$/i)) {
+ throw new sjcl.exception.invalid("json encode: invalid property name");
+ }
+ out += comma + i + ':';
+ comma = ',';
+
+ switch (typeof obj[i]) {
+ case 'number':
+ case 'boolean':
+ out += obj[i];
+ break;
+
+ case 'string':
+ out += '"' + escape(obj[i]) + '"';
+ break;
+
+ case 'object':
+ out += '"' + sjcl.codec.base64.fromBits(obj[i],1) + '"';
+ break;
+
+ default:
+ throw new sjcl.exception.bug("json encode: unsupported type");
+ }
+ }
+ }
+ return out+'}';
+ },
+
+ /** Decode a simple (flat) JSON string into a structure. The ciphertext,
+ * adata, salt and iv will be base64-decoded.
+ * @param {String} str The string.
+ * @return {Object} The decoded structure.
+ * @throws {sjcl.exception.invalid} if str isn't (simple) JSON.
+ */
+ decode: function (str) {
+ str = str.replace(/\s/g,'');
+ if (!str.match(/^\{.*\}$/)) {
+ throw new sjcl.exception.invalid("json decode: this isn't json!");
+ }
+ var a = str.replace(/^\{|\}$/g, '').split(/,/), out={}, i, m;
+ for (i=0; i bs) {
+ key = Hash.hash(key);
+ }
+
+ for (i=0; i>>31,
+ x[1]<<1 ^ x[2]>>>31,
+ x[2]<<1 ^ x[3]>>>31,
+ x[3]<<1 ^ (x[0]>>>31)*0x87];
+ }
+};
diff --git a/core/pbkdf2.js b/core/pbkdf2.js
new file mode 100644
index 00000000..869e4dfa
--- /dev/null
+++ b/core/pbkdf2.js
@@ -0,0 +1,54 @@
+/** @fileOverview Password-based key-derivation function, version 2.0.
+ *
+ * @author Emily Stark
+ * @author Mike Hamburg
+ * @author Dan Boneh
+ */
+
+/** Password-Based Key-Derivation Function, version 2.0.
+ *
+ * Generate keys from passwords using PBKDF2-HMAC-SHA256.
+ *
+ * This is the method specified by RSA's PKCS #5 standard.
+ *
+ * @param {bitArray|String} password The password.
+ * @param {bitArray} salt The salt. Should have lots of entropy.
+ * @param {Number} [count=1000] The number of iterations. Higher numbers make the function slower but more secure.
+ * @param {Number} [length] The length of the derived key. Defaults to the
+ output size of the hash function.
+ * @param {Object} [Prff=sjcl.misc.hmac] The pseudorandom function family.
+ * @return {bitArray} the derived key.
+ */
+sjcl.misc.pbkdf2 = function (password, salt, count, length, Prff) {
+ count = count || 1000;
+
+ if (length < 0 || count < 0) {
+ throw sjcl.exception.invalid("invalid params to pbkdf2");
+ }
+
+ if (typeof password === "string") {
+ password = sjcl.codec.utf8String.toBits(password);
+ }
+
+ Prff = Prff || sjcl.misc.hmac;
+
+ var prf = new Prff(password),
+ u, ui, i, j, k, out = [], b = sjcl.bitArray;
+
+ for (k = 1; 32 * out.length < (length || 1); k++) {
+ u = ui = prf.encrypt(b.concat(salt,[k]));
+
+ for (i=1; i
+ * This random number generator is a derivative of Ferguson and Schneier's
+ * generator Fortuna. It collects entropy from various events into several
+ * pools, implemented by streaming SHA-256 instances. It differs from
+ * ordinary Fortuna in a few ways, though.
+ *
+ *
+ *
+ * Most importantly, it has an entropy estimator. This is present because
+ * there is a strong conflict here between making the generator available
+ * as soon as possible, and making sure that it doesn't "run on empty".
+ * In Fortuna, there is a saved state file, and the system is likely to have
+ * time to warm up.
+ *
+ *
+ *
+ * Second, because users are unlikely to stay on the page for very long,
+ * and to speed startup time, the number of pools increases logarithmically:
+ * a new pool is created when the previous one is actually used for a reseed.
+ * This gives the same asymptotic guarantees as Fortuna, but gives more
+ * entropy to early reseeds.
+ *
+ *
+ *
+ * The entire mechanism here feels pretty klunky. Furthermore, there are
+ * several improvements that should be made, including support for
+ * dedicated cryptographic functions that may be present in some browsers;
+ * state files in local storage; cookies containing randomness; etc. So
+ * look for improvements in future versions.
+ *
+ */
+sjcl.random = {
+ /** Generate several random words, and return them in an array
+ * @param {Number} nwords The number of words to generate.
+ */
+ randomWords: function (nwords, paranoia) {
+ var out = [], i, readiness = this.isReady(paranoia), g;
+
+ if (readiness === this._NOT_READY) {
+ throw new sjcl.exception.notready("generator isn't seeded");
+ } else if (readiness & this._REQUIRES_RESEED) {
+ this._reseedFromPools(!(readiness & this._READY));
+ }
+
+ for (i=0; i0) {
+ estimatedEntropy++;
+ tmp = tmp >>> 1;
+ }
+ }
+ }
+ this._pools[robin].update([id,this._eventId++,ty||2,estimatedEntropy,t,data.length].concat(data));
+ break;
+
+ case "string":
+ if (estimatedEntropy === undefined) {
+ /* English text has just over 1 bit per character of entropy.
+ * But this might be HTML or something, and have far less
+ * entropy than English... Oh well, let's just say one bit.
+ */
+ estimatedEntropy = data.length;
+ }
+ this._pools[robin].update([id,this._eventId++,3,estimatedEntropy,t,data.length]);
+ this._pools[robin].update(data);
+ break;
+
+ default:
+
+ throw new sjcl.exception.bug("random: addEntropy only supports number, array or string");
+ }
+
+ /* record the new strength */
+ this._poolEntropy[robin] += estimatedEntropy;
+ this._poolStrength += estimatedEntropy;
+
+ /* fire off events */
+ if (oldReady === this._NOT_READY) {
+ if (this.isReady() !== this._NOT_READY) {
+ this._fireEvent("seeded", Math.max(this._strength, this._poolStrength));
+ }
+ this._fireEvent("progress", this.getProgress());
+ }
+ },
+
+ /** Is the generator ready? */
+ isReady: function (paranoia) {
+ var entropyRequired = this._PARANOIA_LEVELS[ (paranoia !== undefined) ? paranoia : this._defaultParanoia ];
+
+ if (this._strength && this._strength >= entropyRequired) {
+ return (this._poolEntropy[0] > this._BITS_PER_RESEED && (new Date()).valueOf() > this._nextReseed) ?
+ this._REQUIRES_RESEED | this._READY :
+ this._READY;
+ } else {
+ return (this._poolStrength >= entropyRequired) ?
+ this._REQUIRES_RESEED | this._NOT_READY :
+ this._NOT_READY;
+ }
+ },
+
+ /** Get the generator's progress toward readiness, as a fraction */
+ getProgress: function (paranoia) {
+ var entropyRequired = this._PARANOIA_LEVELS[ paranoia ? paranoia : this._defaultParanoia ];
+
+ if (this._strength >= entropyRequired) {
+ return 1.0;
+ } else {
+ return (this._poolStrength > entropyRequired) ?
+ 1.0 :
+ this._poolStrength / entropyRequired;
+ }
+ },
+
+ /** start the built-in entropy collectors */
+ startCollectors: function () {
+ if (this._collectorsStarted) { return; }
+
+ if (window.addEventListener) {
+ window.addEventListener("load", this._loadTimeCollector, false);
+ window.addEventListener("mousemove", this._mouseCollector, false);
+ } else if (document.attachEvent) {
+ document.attachEvent("onload", this._loadTimeCollector);
+ document.attachEvent("onmousemove", this._mouseCollector);
+ }
+ else {
+ throw new sjcl.exception.bug("can't attach event");
+ }
+
+ this._collectorsStarted = true;
+ },
+
+ /** stop the built-in entropy collectors */
+ stopCollectors: function () {
+ if (!this._collectorsStarted) { return; }
+
+ if (window.removeEventListener) {
+ window.removeEventListener("load", this._loadTimeCollector);
+ window.removeEventListener("mousemove", this._mouseCollector);
+ } else if (window.detachEvent) {
+ window.detachEvent("onload", this._loadTimeCollector);
+ window.detachEvent("onmousemove", this._mouseCollector);
+ }
+ this._collectorsStarted = false;
+ },
+
+ /* use a cookie to store entropy.
+ useCookie: function (all_cookies) {
+ throw new sjcl.exception.bug("random: useCookie is unimplemented");
+ },*/
+
+ /** add an event listener for progress or seeded-ness. */
+ addEventListener: function (name, callback) {
+ this._callbacks[name][this._callbackI++] = callback;
+ },
+
+ /** remove an event listener for progress or seeded-ness */
+ removeEventListener: function (name, cb) {
+ var i, j, cbs=this._callbacks[name], jsTemp=[];
+
+ /* I'm not sure if this is necessary; in C++, iterating over a
+ * collection and modifying it at the same time is a no-no.
+ */
+
+ for (j in cbs) {
+ if (cbs.hasOwnProperty[j] && cbs[j] === cb) {
+ jsTemp.push(j);
+ }
+ }
+
+ for (i=0; i= 1 << this._pools.length) {
+ this._pools.push(new sjcl.hash.sha256());
+ this._poolEntropy.push(0);
+ }
+
+ /* how strong was this reseed? */
+ this._poolStrength -= strength;
+ if (strength > this._strength) {
+ this._strength = strength;
+ }
+
+ this._reseedCount ++;
+ this._reseed(reseedData);
+ },
+
+ _mouseCollector: function (ev) {
+ var x = ev.x || ev.clientX || ev.offsetX, y = ev.y || ev.clientY || ev.offsetY;
+ sjcl.random.addEntropy([x,y], 2, "mouse");
+ },
+
+ _loadTimeCollector: function (ev) {
+ var d = new Date();
+ sjcl.random.addEntropy(d, 2, "loadtime");
+ },
+
+ _fireEvent: function (name, arg) {
+ var j, cbs=sjcl.random._callbacks[name], cbsTemp=[];
+ /* TODO: there is a race condition between removing collectors and firing them */
+
+ /* I'm not sure if this is necessary; in C++, iterating over a
+ * collection and modifying it at the same time is a no-no.
+ */
+
+ for (j in cbs) {
+ if (cbs.hasOwnProperty(j)) {
+ cbsTemp.push(cbs[j]);
+ }
+ }
+
+ for (j=0; j>>7 ^ a>>>18 ^ a>>>3 ^ a<<25 ^ a<<14) +
+ (b>>>17 ^ b>>>19 ^ b>>>10 ^ b<<15 ^ b<<13) +
+ w[i&15] + w[(i+9) & 15]) | 0;
+ }
+
+ tmp = (tmp + h7 + (h4>>>6 ^ h4>>>11 ^ h4>>>25 ^ h4<<26 ^ h4<<21 ^ h4<<7) + (h6 ^ h4&(h5^h6)) + k[i]); // | 0;
+
+ // shift register
+ h7 = h6; h6 = h5; h5 = h4;
+ h4 = h3 + tmp | 0;
+ h3 = h2; h2 = h1; h1 = h0;
+
+ h0 = (tmp + ((h1&h2) ^ (h3&(h1^h2))) + (h1>>>2 ^ h1>>>13 ^ h1>>>22 ^ h1<<30 ^ h1<<19 ^ h1<<10)) | 0;
+ }
+
+ h[0] = h[0]+h0 | 0;
+ h[1] = h[1]+h1 | 0;
+ h[2] = h[2]+h2 | 0;
+ h[3] = h[3]+h3 | 0;
+ h[4] = h[4]+h4 | 0;
+ h[5] = h[5]+h5 | 0;
+ h[6] = h[6]+h6 | 0;
+ h[7] = h[7]+h7 | 0;
+ }
+};
+
+
diff --git a/core/sjcl.js b/core/sjcl.js
new file mode 100644
index 00000000..e3644217
--- /dev/null
+++ b/core/sjcl.js
@@ -0,0 +1,60 @@
+/** @fileOverview Javascript cryptography implementation.
+ *
+ * Crush to remove comments, shorten variable names and
+ * generally reduce transmission size.
+ *
+ * @author Emily Stark
+ * @author Mike Hamburg
+ * @author Dan Boneh
+ */
+
+"use strict";
+/*jslint indent: 2, bitwise: false, nomen: false, plusplus: false, white: false, regexp: false */
+/*global document, window, escape, unescape */
+
+/** @namespace The Stanford Javascript Crypto Library, top-level namespace. */
+var sjcl = {
+ /** @namespace Symmetric ciphers. */
+ cipher: {},
+
+ /** @namespace Hash functions. Right now only SHA256 is implemented. */
+ hash: {},
+
+ /** @namespace Block cipher modes of operation. */
+ mode: {},
+
+ /** @namespace Miscellaneous. HMAC and PBKDF2. */
+ misc: {},
+
+ /**
+ * @namespace Bit array encoders and decoders.
+ *
+ * @description
+ * The members of this namespace are functions which translate between
+ * SJCL's bitArrays and other objects (usually strings). Because it
+ * isn't always clear which direction is encoding and which is decoding,
+ * the method names are "fromBits" and "toBits".
+ */
+ codec: {},
+
+ /** @namespace Exceptions. */
+ exception: {
+ /** @class Ciphertext is corrupt. */
+ corrupt: function(message) {
+ this.toString = function() { return "CORRUPT: "+this.message; };
+ this.message = message;
+ },
+
+ /** @class Invalid parameter. */
+ invalid: function(message) {
+ this.toString = function() { return "INVALID: "+this.message; };
+ this.message = message;
+ },
+
+ /** @class Bug or missing feature in SJCL. */
+ bug: function(message) {
+ this.toString = function() { return "BUG: "+this.message; };
+ this.message = message;
+ }
+ }
+};
diff --git a/demo/alpha-arrow.png b/demo/alpha-arrow.png
new file mode 100644
index 00000000..e4334a7d
Binary files /dev/null and b/demo/alpha-arrow.png differ
diff --git a/demo/example.css b/demo/example.css
new file mode 100644
index 00000000..7fcfb737
--- /dev/null
+++ b/demo/example.css
@@ -0,0 +1,179 @@
+* {
+ margin: 0px;
+ padding: 0px;
+ font-family: Arial, Helvetica, FreeSans, sans;
+}
+
+h1 {
+ text-align: center;
+ background: #eee;
+ padding: 5px;
+ margin-bottom: 0.6em;
+ font-size: 1.5em;
+}
+
+.header {
+ width: 650px;
+ margin: 0px auto 1em;
+}
+
+p+p {
+ margin-top: 1em;
+}
+
+.explanation {
+ color: #555;
+ margin-top: 0.3em;
+}
+
+.section+.section, .explanation+.section {
+ margin-top: 1.5em;
+}
+
+.hex {
+ text-transform: uppercase;
+}
+
+.hex, .base64, #ciphertext {
+ font-family: 'Courier', mono;
+}
+
+.wide, textarea {
+ width: 100%;
+ margin: 0px -4px;
+ font-size: inherit;
+ text-align: left;
+}
+
+textarea+*, .wide+* {
+ margin-top: 0.3em;
+}
+
+/* bulk object placement */
+#theForm {
+ position: relative;
+ width: 940px;
+ margin: 0px auto;
+ font-size: 0.8em;
+}
+
+.column {
+ top: 0px;
+ width: 300px;
+}
+
+.box {
+ border: 2px solid #999;
+ padding: 7px;
+ margin-bottom: 20px;
+ -moz-border-radius: 7px;
+ -webkit-border-radius: 7px;
+}
+
+#cmode { position: absolute; left: 640px; }
+#ctexts { position: absolute; left: 320px; }
+
+.floatright {
+ float: right;
+ text-align: right;
+}
+
+a {
+ cursor: pointer;
+ color: #282;
+}
+
+a.random, #buttons a { text-decoration: none; }
+a.random:hover, a.random:focus { text-decoration: underline; }
+
+h2 {
+ margin: -7px -7px 3px -7px;
+ text-align: center;
+ font-size: 1.2em;
+ color: white;
+ background: #999;
+}
+
+#pplaintext { border-color: #f65; }
+#pplaintext h2 { background: #f65; }
+
+#ppassword { border-color: #4a4; }
+#ppassword h2 { background: #4a4; }
+
+#pciphertext { border-color: #78f; }
+#pciphertext h2 { background: #78f; }
+
+#buttons { text-align: center; margin-top: -20px; }
+
+a#doPbkdf2, a#encrypt, a#decrypt {
+ display: inline-block;
+ text-align: center;
+ height: 43px;
+ padding-top: 20px;
+ width: 50px;
+ background: url('alpha-arrow.png') no-repeat bottom center;
+ vertical-align: middle;
+ border: none;
+ color: white;
+ overflow: hidden;
+}
+
+.turnDown {
+ display: inline-block;
+ padding-bottom: 3px;
+ -moz-transform: rotate(90deg);
+ -webkit-transform: rotate(90deg);
+ transform: rotate(90deg);
+ background-color: inherit;
+}
+
+.turnUp {
+ display: inline-block;
+ padding-bottom: 3px;
+ -moz-transform: rotate(-90deg);
+ -webkit-transform: rotate(-90deg);
+ transform: rotate(-90deg);
+ background-color: inherit;
+}
+
+.buttons a.disabled {
+ background-color: #ccc ! important;
+ cursor: inherit ! important;
+}
+
+a#encrypt { background-color: #f65; margin-bottom: 2px; }
+a#encrypt:hover, a#encrypt:focus { background-color: #f76; }
+a#encrypt:active { background-color: #f87; }
+
+a#decrypt {
+ height: 36px;
+ padding-top: 27px;
+ background: url('alpha-arrow.png') no-repeat top center;
+ background-color: #78f;
+ margin-top: 2px;
+}
+a#decrypt:hover { background-color: #89f; }
+a#decrypt:focus { background-color: #89f; }
+a#decrypt:active { background-color: #9af; }
+
+#ppassword, #pkey, #pmode, #pplaintext, #pciphertext {
+ -moz-border-radius: 7px;
+ -webkit-border-radius: 7px;
+}
+input[type='text'], input[type='password'], textarea {
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ font-size: inherit;
+ border: 1px solid #444;
+ padding: 3px;
+}
+
+input[type='text']:focus, input[type='password']:focus, textarea:focus {
+ border-color: red;
+}
+
+input[type="radio"], input[type="checkbox"] {
+ position: relative;
+ top: 0.15em;
+ margin-right: -0.15em;
+}
diff --git a/demo/example.js b/demo/example.js
new file mode 100644
index 00000000..99363d5d
--- /dev/null
+++ b/demo/example.js
@@ -0,0 +1,153 @@
+/* keep track of which salts have been used. */
+var form, usedIvs = {'':1}, usedSalts = {'':1};
+
+/* enter actions */
+var enterActions = {
+ password: doPbkdf2,
+ salt: doPbkdf2,
+ iter: doPbkdf2
+};
+
+function loaded() {
+ form = new formHandler('theForm', enterActions);
+ form._extendedKey = [];
+ sjcl.random.startCollectors();
+ document.getElementById("password").focus();
+}
+
+/* there's probaby a better way to tell the user something, but oh well */
+function error(x) {
+ alert(x);
+}
+
+/* compute PBKDF2 on the password. */
+function doPbkdf2(decrypting) {
+ var v = form.get(), salt=v.salt, key, hex = sjcl.codec.hex.fromBits, p={},
+ password = v.password;
+
+ p.iter = v.iter;
+
+ if (password.length == 0) {
+ if (decrypting) { error("Can't decrypt: need a password!"); }
+ return;
+ }
+
+ if (salt.length === 0 && decrypting) {
+ error("Can't decrypt: need a salt for PBKDF2!");
+ return;
+ }
+
+ if (decrypting || !v.freshsalt || !usedSalts[v.salt]) {
+ p.salt = v.salt;
+ }
+
+ p = sjcl.misc.cachedPbkdf2(password, p);
+ form._extendedKey = p.key;
+ v.key = p.key.slice(0, v.keysize/32);
+ v.salt = p.salt;
+
+ form.set(v);
+ form.plaintext.el.select();
+}
+/* Encrypt a message */
+function doEncrypt() {
+ var v = form.get(), iv = v.iv, password = v.password, key = v.key, adata = v.adata, aes, plaintext=v.plaintext, rp = {}, ct, p;
+
+ if (plaintext === '' && v.ciphertext.length) { return; }
+ if (key.length == 0 && password.length == 0) {
+ error("need a password or key!");
+ return;
+ }
+
+ p = { adata:v.adata,
+ iter:v.iter,
+ mode:v.mode,
+ ts:parseInt(v.tag),
+ ks:parseInt(v.keysize) };
+ if (!v.freshiv || !usedIvs[v.iv]) { iv:v.iv; }
+ if (!v.freshsalt || !usedSalts[v.salt]) { p.salt = v.salt; }
+ ct = sjcl.encrypt(password || key, plaintext, p, rp).replace(/,/g,",\n");
+
+ v.iv = rp.iv;
+ usedIvs[rp.iv] = 1;
+ if (rp.salt) {
+ v.salt = rp.salt;
+ usedSalts[rp.salt] = 1;
+ }
+ v.key = rp.key;
+
+ if (v.json) {
+ v.ciphertext = ct;
+ v.adata = '';
+ } else {
+ v.ciphertext = ct.match(/ct:"([^"]*)"/)[1]; //"
+ }
+
+ v.plaintext = '';
+
+ form.set(v);
+ form.ciphertext.el.select();
+}
+
+/* Decrypt a message */
+function doDecrypt() {
+ var v = form.get(), iv = v.iv, key = v.key, adata = v.adata, aes, ciphertext=v.ciphertext, rp = {};
+
+ if (ciphertext.length === 0) { return; }
+ if (!v.password && !v.key.length) {
+ error("Can't decrypt: need a password or key!"); return;
+ }
+
+ if (ciphertext.match("{")) {
+ /* it's jsonized */
+ try {
+ v.plaintext = sjcl.decrypt(v.password || v.key, ciphertext, {}, rp);
+ } catch(e) {
+ error("Can't decrypt: "+e);
+ return;
+ }
+ v.mode = rp.mode;
+ v.iv = rp.iv;
+ v.adata = rp.adata;
+ if (v.password) {
+ v.salt = rp.salt;
+ v.iter = rp.iter;
+ v.keysize = rp.ks;
+ v.tag = rp.ts;
+ }
+ v.key = rp.key;
+ v.ciphertext = "";
+ document.getElementById('plaintext').select();
+ } else {
+ /* it's raw */
+ ciphertext = sjcl.codec.base64.toBits(ciphertext);
+ if (iv.length === 0) {
+ error("Can't decrypt: need an IV!"); return;
+ }
+ if (key.length === 0) {
+ if (v.password.length) {
+ doPbkdf2(true);
+ key = v.key;
+ }
+ }
+ aes = new sjcl.cipher.aes(key);
+
+ try {
+ v.plaintext = sjcl.codec.utf8String.fromBits(sjcl.mode[v.mode].decrypt(aes, ciphertext, iv, v.adata, v.tag));
+ v.ciphertext = "";
+ document.getElementById('plaintext').select();
+ } catch (e) {
+ error("Can't decrypt: " + e);
+ }
+ }
+ form.set(v);
+}
+
+function extendKey(size) {
+ form.key.set(form._extendedKey.slice(0,size));
+}
+
+function randomize(field, words, paranoia) {
+ form[field].set(sjcl.random.randomWords(words, paranoia));
+ if (field == 'salt') { form.key.set([]); }
+}
diff --git a/demo/form.js b/demo/form.js
new file mode 100644
index 00000000..0cd4224f
--- /dev/null
+++ b/demo/form.js
@@ -0,0 +1,137 @@
+/* Hackish form handling system. */
+function hasClass(e, cl) {
+ return (" "+e.className+" ").match(" "+cl+" ");
+}
+
+function stopPropagation(e) {
+ e.preventDefault && e.preventDefault();
+ e.cancelBubble = true;
+}
+
+/* proxy for a form object, with appropriate encoder/decoder */
+function formElement(el) {
+ this.el = el;
+}
+formElement.prototype = {
+ get: function() {
+ var el = this.el;
+ if (el.type == "checkbox") {
+ return el.checked;
+ } else if (hasClass(el, "numeric")) {
+ return parseInt(el.value);
+ } else if (hasClass(el, "hex")) {
+ return sjcl.codec.hex.toBits(el.value);
+ } else if (hasClass(el, "base64")) {
+ return sjcl.codec.base64.toBits(el.value);
+ } else {
+ return el.value;
+ }
+ },
+
+ set: function(x) {
+ var el = this.el;
+ if (el.type == "checkbox") {
+ el.checked = x; return;
+ } else if (hasClass(el, "hex")) {
+ if (typeof x !== 'string') {
+ x = sjcl.codec.hex.fromBits(x);
+ }
+ x = x.toUpperCase().replace(/ /g,'').replace(/(.{8})/g, "$1 ").replace(/ $/, '');
+ } else if (hasClass(el, "base64")) {
+ if (typeof x !== 'string') {
+ x = sjcl.codec.base64.fromBits(x);
+ }
+ x = x.replace(/\s/g,'').replace(/(.{32})/g, "$1\n").replace(/\n$/, '');
+ }
+ el.value = x;
+ }
+}
+
+function radioGroup(name) {
+ this.name = name;
+}
+radioGroup.prototype = {
+ get: function() {
+ var els = document.getElementsByName(this.name), i;
+ for (i=0; i
+
+
+
+ SJCL demo
+
+
+
+
+
+
+
SJCL demo
+
+
+
This page is a demo of the Stanford Javascript Crypto Library. To get started, just type in a password in the left pane and a secret message in the middle pane, then click "encrypt". Encryption takes place in your browser and we never see the plaintext.
+
+
SJCL has lots of other options, many of which are shown in the grey boxes.