There are no secrets better kept than the secrets that everybody guesses. default tip

Wed, 16 Feb 2011 20:29:33 +0000

author
Matthew Wild <mwild1@gmail.com>
date
Wed, 16 Feb 2011 20:29:33 +0000
changeset 0
598d09faf89c

There are no secrets better kept than the secrets that everybody guesses.

COPYING file | annotate | diff | comparison | revisions
README file | annotate | diff | comparison | revisions
aeslua/Copyright.txt file | annotate | diff | comparison | revisions
aeslua/License.txt file | annotate | diff | comparison | revisions
aeslua/README file | annotate | diff | comparison | revisions
aeslua/aes.lua file | annotate | diff | comparison | revisions
aeslua/buffer.lua file | annotate | diff | comparison | revisions
aeslua/ciphermode.lua file | annotate | diff | comparison | revisions
aeslua/gf.lua file | annotate | diff | comparison | revisions
aeslua/init.lua file | annotate | diff | comparison | revisions
aeslua/util.lua file | annotate | diff | comparison | revisions
crc16/crc16.lua file | annotate | diff | comparison | revisions
squishy file | annotate | diff | comparison | revisions
yubikey/init.lua file | annotate | diff | comparison | revisions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/COPYING	Wed Feb 16 20:29:33 2011 +0000
@@ -0,0 +1,20 @@
+Copyright (c) 2011 Matthew Wild
+(excluding aeslua - see README)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README	Wed Feb 16 20:29:33 2011 +0000
@@ -0,0 +1,17 @@
+YubiKey token parsing and validation for Lua
+--- --- --- --- --- ---- --- --- --- --- ---
+
+This library allows you to parse OTP tokens from a YubiKey
+device, and also provides a validation framework for people
+who want to integrate OTP authentication into their applications.
+
+\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
+NOTE: This project is MIT/X11 licensed - however the project     >
+      contains modified parts of aeslua, which is LGPL-licensed. >
+      Since LGPL is more restrictive than MIT, you should take   >
+      care to obey its requirements when using yubikey.lua in    >
+      your projects. See the docs in aeslua/ for more details.   >
+/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
+
+The easiest way to use this library is to run 'squish' in its
+directory. Squish can be found at http://matthewwild.co.uk/projects/squish
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aeslua/Copyright.txt	Wed Feb 16 20:29:33 2011 +0000
@@ -0,0 +1,26 @@
+aeslua: Lua AES implementation
+Copyright (c) 2006,2007 Matthias Hilbig
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser Public License as published by the
+Free Software Foundation; either version 2.1 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
+Lesser Public License for more details.
+
+A copy of the terms and conditions of the license can be found in
+License.txt or online at
+
+    http://www.gnu.org/copyleft/lesser.html
+
+To obtain a copy, write to the Free Software Foundation, Inc.,
+59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+Author
+-------
+Matthias Hilbig
+http://homepages.upb.de/hilbig/aeslua/
+hilbig@upb.de
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aeslua/License.txt	Wed Feb 16 20:29:33 2011 +0000
@@ -0,0 +1,450 @@
+----------------------------------------------------------------------
+The aeslua (all versions) is provided under the terms and
+conditions of the GNU Lesser General Public Library, which is stated
+below.  It can also be found at:
+
+   http://www.gnu.org/copyleft/lesser.html
+
+----------------------------------------------------------------------
+
+GNU LESSER GENERAL PUBLIC LICENSE
+
+Version 2.1, February 1999
+
+Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+as the successor of the GNU Library Public License, version 2, hence the
+version number 2.1.]
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public Licenses are
+intended to guarantee your freedom to share and change free software--to
+make sure the software is free for all its users.
+
+This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the Free
+Software Foundation and other authors who decide to use it. You can use
+it too, but we suggest you first think carefully about whether this
+license or the ordinary General Public License is the better strategy to
+use in any particular case, based on the explanations below.
+
+When we speak of free software, we are referring to freedom of use, 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 and use pieces of it in
+new free programs; and that you are informed that you can do these
+things.
+
+To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for you
+if you distribute copies of the library or if you modify it.
+
+For example, if you distribute copies of the library, whether gratis or
+for a fee, you must give the recipients all the rights that we gave you.
+You must make sure that they, too, receive or can get the source code.
+If you link other code with the library, you must provide complete
+object files to the recipients, so that they can relink them with the
+library after making changes to the library and recompiling it. And you
+must show them these terms so they know their rights.
+
+We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+To protect each distributor, we want to make it very clear that there is
+no warranty for the free library. Also, if the library is modified by
+someone else and passed on, the recipients should know that what they
+have is not the original version, so that the original author's
+reputation will not be affected by problems that might be introduced by
+others.
+
+Finally, software patents pose a constant threat to the existence of any
+free program. We wish to make sure that a company cannot effectively
+restrict the users of a free program by obtaining a restrictive license
+from a patent holder. Therefore, we insist that any patent license
+obtained for a version of the library must be consistent with the full
+freedom of use specified in this license.
+
+Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License. This license, the GNU Lesser General Public
+License, applies to certain designated libraries, and is quite different
+from the ordinary General Public License. We use this license for
+certain libraries in order to permit linking those libraries into
+non-free programs.
+
+When a program is linked with a library, whether statically or using a
+shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the entire
+combination fits its criteria of freedom. The Lesser General Public
+License permits more lax criteria for linking other code with the
+library.
+
+We call this license the "Lesser" General Public License because it does
+Less to protect the user's freedom than the ordinary General Public
+License. It also provides other free software developers Less of an
+advantage over competing non-free programs. These disadvantages are the
+reason we use the ordinary General Public License for many libraries.
+However, the Lesser license provides advantages in certain special
+circumstances.
+
+For example, on rare occasions, there may be a special need to encourage
+the widest possible use of a certain library, so that it becomes a
+de-facto standard. To achieve this, non-free programs must be allowed to
+use the library. A more frequent case is that a free library does the
+same job as widely used non-free libraries. In this case, there is
+little to gain by limiting the free library to free software only, so we
+use the Lesser General Public License.
+
+In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of free
+software. For example, permission to use the GNU C Library in non-free
+programs enables many more people to use the whole GNU operating system,
+as well as its variant, the GNU/Linux operating system.
+
+Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is linked
+with the Library has the freedom and the wherewithal to run that program
+using a modified version of the Library.
+
+The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or other
+authorized party saying it may be distributed under the terms of this
+Lesser General Public License (also called "this License"). Each
+licensee is addressed as "you".
+
+A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+The "Library", below, refers to any such software library or work which
+has been distributed under these terms. A "work based on the Library"
+means either the Library or any derivative work under copyright law:
+that is to say, a work containing the Library or a portion of it, either
+verbatim or with modifications and/or translated straightforwardly into
+another language. (Hereinafter, translation is included without
+limitation in the term "modification".)
+
+"Source code" for a work means the preferred form of the work for making
+modifications to it. For a library, 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 library.
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of running
+a program using the Library is not restricted, and output from such a
+program is covered only if its contents constitute a work based on the
+Library (independent of the use of the Library in a tool for writing
+it). Whether that is true depends on what the Library does and what the
+program that uses the Library does.
+
+1. You may copy and distribute verbatim copies of the Library's complete
+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
+distribute a copy of this License along with the Library.
+
+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 Library or any portion of
+it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
+    b) You must cause the files modified to carry prominent notices
+       stating that you changed the files and the date of any change.
+    c) You must cause the whole of the work to be licensed at no
+       charge to all third parties under the terms of this License.
+    d) If a facility in the modified Library refers to a function or a
+       table of data to be supplied by an application program that uses
+       the facility, other than as an argument passed when the facility
+       is invoked, then you must make a good faith effort to ensure that,
+       in the event an application does not supply such function or
+       table, the facility still operates, and performs whatever part of
+       its purpose remains meaningful.
+
+      (For example, a function in a library to compute square roots has
+a purpose that is entirely well-defined independent of the application.
+Therefore, Subsection 2d requires that any application-supplied function
+or table used by this function must be optional: if the application does
+not supply it, the square root function must still compute square
+roots.)
+
+      These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library, 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 Library, 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 Library.
+
+      In addition, mere aggregation of another work not based on the
+Library with the Library (or with a work based on the Library) on a
+volume of a storage or distribution medium does not bring the other work
+under the scope of this License. 
+
+3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so that
+they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in these
+notices.
+
+Once this change is made in a given copy, it is irreversible for that
+copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+This option is useful when you wish to copy part of the code of the
+Library into a program that is not a library.
+
+4. You may copy and distribute the Library (or a portion or derivative
+of it, under Section 2) in object code or executable form under the
+terms of Sections 1 and 2 above provided that you 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.
+
+If distribution of 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 satisfies the requirement to distribute the
+source code, even though third parties are not compelled to copy the
+source along with the object code.
+
+5. A program that contains no derivative of any portion of the Library,
+but is designed to work with the Library by being compiled or linked
+with it, is called a "work that uses the Library". Such a work, in
+isolation, is not a derivative work of the Library, and therefore falls
+outside the scope of this License.
+
+However, linking a "work that uses the Library" with the Library creates
+an executable that is a derivative of the Library (because it contains
+portions of the Library), rather than a "work that uses the library".
+The executable is therefore covered by this License. Section 6 states
+terms for distribution of such executables.
+
+When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be linked
+without the Library, or if the work is itself a library. The threshold
+for this to be true is not precisely defined by law.
+
+If such an object file uses only numerical parameters, data structure
+layouts and accessors, and small macros and small inline functions (ten
+lines or less in length), then the use of the object file is
+unrestricted, regardless of whether it is legally a derivative work.
+(Executables containing this object code plus portions of the Library
+will still fall under Section 6.)
+
+Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6, whether
+or not they are linked directly with the Library itself.
+
+6. As an exception to the Sections above, you may also combine or link a
+"work that uses the Library" with the Library to produce a work
+containing portions of the Library, and distribute that work under terms
+of your choice, provided that the terms permit modification of the work
+for the customer's own use and reverse engineering for debugging such
+modifications.
+
+You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work during
+execution displays copyright notices, you must include the copyright
+notice for the Library among them, as well as a reference directing the
+user to the copy of this License. Also, you must do one of these things:
+
+    a) Accompany the work with the complete corresponding
+       machine-readable source code for the Library including whatever
+       changes were used in the work (which must be distributed under
+       Sections 1 and 2 above); and, if the work is an executable linked
+       with the Library, with the complete machine-readable "work that
+       uses the Library", as object code and/or source code, so that the
+       user can modify the Library and then relink to produce a modified
+       executable containing the modified Library. (It is understood that
+       the user who changes the contents of definitions files in the
+       Library will not necessarily be able to recompile the application
+       to use the modified definitions.)
+    b) Use a suitable shared library mechanism for linking with the
+       Library. A suitable mechanism is one that (1) uses at run time a
+       copy of the library already present on the user's computer system,
+       rather than copying library functions into the executable, and (2)
+       will operate properly with a modified version of the library, if
+       the user installs one, as long as the modified version is
+       interface-compatible with the version that the work was made with.
+    c) Accompany the work with a written offer, valid for at least
+       three years, to give the same user the materials specified in
+       Subsection 6a, above, for a charge no more than the cost of
+       performing this distribution.
+    d) If distribution of the work is made by offering access to copy
+       from a designated place, offer equivalent access to copy the above
+       specified materials from the same place.
+    e) Verify that the user has already received a copy of these
+       materials or that you have already sent this user a copy. 
+
+For an executable, the required form of the "work that uses the Library"
+must include any data and utility programs needed for reproducing the
+executable from it. However, as a special exception, the materials to be
+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.
+
+It may happen that this requirement contradicts the license restrictions
+of other proprietary libraries that do not normally accompany the
+operating system. Such a contradiction means you cannot use both them
+and the Library together in an executable that you distribute.
+
+7. You may place library facilities that are a work based on the Library
+side-by-side in a single library together with other library facilities
+not covered by this License, and distribute such a combined library,
+provided that the separate distribution of the work based on the Library
+and of the other library facilities is otherwise permitted, and provided
+that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+       based on the Library, uncombined with any other library
+       facilities. This must be distributed under the terms of the
+       Sections above.
+    b) Give prominent notice with the combined library of the fact
+       that part of it is a work based on the Library, and explaining
+       where to find the accompanying uncombined form of the same work. 
+
+8. You may not copy, modify, sublicense, link with, or distribute the
+Library except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense, link with, or distribute the
+Library 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.
+
+9. 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 Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and all
+its terms and conditions for copying, distributing or modifying the
+Library or works based on it.
+
+10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+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 with
+this License.
+
+11. 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 Library at all. For example, if a patent license would
+not permit royalty-free redistribution of the Library 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 Library.
+
+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.
+
+12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library 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.
+
+13. The Free Software Foundation may publish revised and/or new versions
+of the Lesser 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 Library
+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 Library does not specify a license
+version number, you may choose any version ever published by the Free
+Software Foundation.
+
+14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+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
+
+15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE LIBRARY "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 LIBRARY IS WITH
+YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+16. 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 LIBRARY 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 LIBRARY
+(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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR
+OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aeslua/README	Wed Feb 16 20:29:33 2011 +0000
@@ -0,0 +1,48 @@
+AES for lua
+-----------
+
+This files contain an implementation of AES in lua. The only additional library 
+needed is bitlib.
+
+Usage
+-----
+
+aeslua.lua contains a simple API to encrypt and decrypt lua strings.
+
+To encrypt the string "geheim" with the password "password" use:
+
+require("aeslua");
+cipher = aeslua.encrypt("password", "secret");
+
+and to decrypt the string again:
+
+plain = aeslua.decrypt("password", cipher);
+
+You can also specify the key size and the encryption mode. For further examples
+look into the file src/testcryptotest.lua.
+
+To use AES directly, have a look at aes.lua and at the example usage in 
+testaes.lua.
+
+Installation
+------------
+
+Edit the LIBDIR variable in the Makefile and run
+
+make install
+
+Speed
+-----
+
+The implementation is rather optimized (it uses tables for most AES operations) 
+but still cannot compete with AES written in other languages. Typical AES 
+implementations reach several 100 MBit per second, this implementation only 
+reaches 400 kBit per second. The most plausible reason is the heavy reliance
+of AES on bit operations. As lua numbers are doubles bitlib needs to convert
+them to long values for each bit operation.
+
+So if you need to encrypt much data with AES, do yourself a favor and use a 
+C-Implementation. But if you only need to encrypt short strings and you have 
+no control over the lua environment (like in games :-)) use this library.
+
+Matthias Hilbig (hilbig@upb.de)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aeslua/aes.lua	Wed Feb 16 20:29:33 2011 +0000
@@ -0,0 +1,509 @@
+local bit = require("bit");
+
+local gf = require("aeslua.gf");
+local util = require("aeslua.util");
+
+--
+-- Implementation of AES with nearly pure lua (only bitlib is needed) 
+--
+-- AES with lua is slow, really slow :-)
+--
+
+local public = {};
+local private = {};
+
+local aeslua = require("aeslua");
+aeslua.aes = public;
+
+-- some constants
+public.ROUNDS = "rounds";
+public.KEY_TYPE = "type";
+public.ENCRYPTION_KEY=1;
+public.DECRYPTION_KEY=2;
+
+-- aes SBOX
+private.SBox = {};
+private.iSBox = {};
+
+-- aes tables
+private.table0 = {};
+private.table1 = {};
+private.table2 = {};
+private.table3 = {};
+
+private.tableInv0 = {};
+private.tableInv1 = {};
+private.tableInv2 = {};
+private.tableInv3 = {};
+
+-- round constants
+private.rCon = {0x01000000, 
+                0x02000000, 
+                0x04000000, 
+                0x08000000, 
+                0x10000000, 
+                0x20000000, 
+                0x40000000, 
+                0x80000000, 
+                0x1b000000, 
+                0x36000000,
+                0x6c000000,
+                0xd8000000,
+                0xab000000,
+                0x4d000000,
+                0x9a000000,
+                0x2f000000};
+
+--
+-- affine transformation for calculating the S-Box of AES
+--
+function private.affinMap(byte)
+    local mask = 0xf8;
+    local result = 0;
+    for i = 1,8 do
+        result = bit.lshift(result,1);
+
+        local parity = util.byteParity(bit.band(byte,mask)); 
+        result = result + parity;
+
+        -- simulate roll
+        local lastbit = bit.band(mask, 1);
+        mask = bit.band(bit.rshift(mask, 1),0xff);
+        if (lastbit ~= 0) then
+            mask = bit.bor(mask, 0x80);
+        else
+            mask = bit.band(mask, 0x7f);
+        end
+    end
+
+    return bit.bxor(result, 0x63);
+end
+
+--
+-- calculate S-Box and inverse S-Box of AES
+-- apply affine transformation to inverse in finite field 2^8 
+--
+function private.calcSBox() 
+    local inverse;
+    for i = 0, 255 do
+        if (i ~= 0) then
+            inverse = gf.invert(i);
+        else
+            inverse = i;
+        end
+        local mapped = private.affinMap(inverse);                 
+        private.SBox[i] = mapped;
+        private.iSBox[mapped] = i;
+    end
+end
+
+--
+-- Calculate round tables
+-- round tables are used to calculate shiftRow, MixColumn and SubBytes 
+-- with 4 table lookups and 4 xor operations.
+--
+function private.calcRoundTables()
+    for x = 0,255 do
+        local byte = private.SBox[x];
+        private.table0[x] = util.putByte(gf.mul(0x03, byte), 0)
+                          + util.putByte(             byte , 1)
+                          + util.putByte(             byte , 2)
+                          + util.putByte(gf.mul(0x02, byte), 3);
+        private.table1[x] = util.putByte(             byte , 0)
+                          + util.putByte(             byte , 1)
+                          + util.putByte(gf.mul(0x02, byte), 2)
+                          + util.putByte(gf.mul(0x03, byte), 3);
+        private.table2[x] = util.putByte(             byte , 0)
+                          + util.putByte(gf.mul(0x02, byte), 1)
+                          + util.putByte(gf.mul(0x03, byte), 2)
+                          + util.putByte(             byte , 3);
+        private.table3[x] = util.putByte(gf.mul(0x02, byte), 0)
+                          + util.putByte(gf.mul(0x03, byte), 1)
+                          + util.putByte(             byte , 2)
+                          + util.putByte(             byte , 3);
+    end
+end
+
+--
+-- Calculate inverse round tables
+-- does the inverse of the normal roundtables for the equivalent 
+-- decryption algorithm.
+--
+function private.calcInvRoundTables()
+    for x = 0,255 do
+        local byte = private.iSBox[x];
+        private.tableInv0[x] = util.putByte(gf.mul(0x0b, byte), 0)
+                             + util.putByte(gf.mul(0x0d, byte), 1)
+                             + util.putByte(gf.mul(0x09, byte), 2)
+                             + util.putByte(gf.mul(0x0e, byte), 3);
+        private.tableInv1[x] = util.putByte(gf.mul(0x0d, byte), 0)
+                             + util.putByte(gf.mul(0x09, byte), 1)
+                             + util.putByte(gf.mul(0x0e, byte), 2)
+                             + util.putByte(gf.mul(0x0b, byte), 3);
+        private.tableInv2[x] = util.putByte(gf.mul(0x09, byte), 0)
+                             + util.putByte(gf.mul(0x0e, byte), 1)
+                             + util.putByte(gf.mul(0x0b, byte), 2)
+                             + util.putByte(gf.mul(0x0d, byte), 3);
+        private.tableInv3[x] = util.putByte(gf.mul(0x0e, byte), 0)
+                             + util.putByte(gf.mul(0x0b, byte), 1)
+                             + util.putByte(gf.mul(0x0d, byte), 2)
+                             + util.putByte(gf.mul(0x09, byte), 3);
+    end
+end
+
+
+--
+-- rotate word: 0xaabbccdd gets 0xbbccddaa
+-- used for key schedule
+--
+function private.rotWord(word)
+    local tmp = bit.band(word,0xff000000);
+    return (bit.lshift(word,8) + bit.rshift(tmp,24)) ;
+end
+
+--
+-- replace all bytes in a word with the SBox.
+-- used for key schedule
+--
+function private.subWord(word)
+    return util.putByte(private.SBox[util.getByte(word,0)],0) 
+         + util.putByte(private.SBox[util.getByte(word,1)],1) 
+         + util.putByte(private.SBox[util.getByte(word,2)],2)
+         + util.putByte(private.SBox[util.getByte(word,3)],3);
+end
+
+--
+-- generate key schedule for aes encryption
+--
+-- returns table with all round keys and
+-- the necessary number of rounds saved in [public.ROUNDS]
+--
+function public.expandEncryptionKey(key)
+    local keySchedule = {};
+    local keyWords = math.floor(#key / 4);
+   
+ 
+    if ((keyWords ~= 4 and keyWords ~= 6 and keyWords ~= 8) or (keyWords * 4 ~= #key)) then
+        error("Invalid key size: "..keyWords);
+        return nil;
+    end
+
+    keySchedule[public.ROUNDS] = keyWords + 6;
+    keySchedule[public.KEY_TYPE] = public.ENCRYPTION_KEY;
+ 
+    for i = 0,keyWords - 1 do
+        keySchedule[i] = util.putByte(key[i*4+1], 3) 
+                       + util.putByte(key[i*4+2], 2)
+                       + util.putByte(key[i*4+3], 1)
+                       + util.putByte(key[i*4+4], 0);  
+    end    
+   
+    for i = keyWords, (keySchedule[public.ROUNDS] + 1)*4 - 1 do
+        local tmp = keySchedule[i-1];
+
+        if ( i % keyWords == 0) then
+            tmp = private.rotWord(tmp);
+            tmp = private.subWord(tmp);
+            
+            local index = math.floor(i/keyWords);
+            tmp = bit.bxor(tmp,private.rCon[index]);
+        elseif (keyWords > 6 and i % keyWords == 4) then
+            tmp = private.subWord(tmp);
+        end
+        
+        keySchedule[i] = bit.bxor(keySchedule[(i-keyWords)],tmp);
+    end
+
+    return keySchedule;
+end
+
+--
+-- Inverse mix column
+-- used for key schedule of decryption key
+--
+function private.invMixColumnOld(word)
+    local b0 = util.getByte(word,3);
+    local b1 = util.getByte(word,2);
+    local b2 = util.getByte(word,1);
+    local b3 = util.getByte(word,0);
+     
+    return util.putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b1), 
+                                             gf.mul(0x0d, b2)), 
+                                             gf.mul(0x09, b3)), 
+                                             gf.mul(0x0e, b0)),3)
+         + util.putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b2), 
+                                             gf.mul(0x0d, b3)), 
+                                             gf.mul(0x09, b0)), 
+                                             gf.mul(0x0e, b1)),2)
+         + util.putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b3), 
+                                             gf.mul(0x0d, b0)), 
+                                             gf.mul(0x09, b1)), 
+                                             gf.mul(0x0e, b2)),1)
+         + util.putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b0), 
+                                             gf.mul(0x0d, b1)), 
+                                             gf.mul(0x09, b2)), 
+                                             gf.mul(0x0e, b3)),0);
+end
+
+-- 
+-- Optimized inverse mix column
+-- look at http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
+-- TODO: make it work
+--
+function private.invMixColumn(word)
+    local b0 = util.getByte(word,3);
+    local b1 = util.getByte(word,2);
+    local b2 = util.getByte(word,1);
+    local b3 = util.getByte(word,0);
+    
+    local t = bit.bxor(b3,b2);
+    local u = bit.bxor(b1,b0);
+    local v = bit.bxor(t,u);
+    v = bit.bxor(v,gf.mul(0x08,v));
+    v = bit.bxor(v,gf.mul(0x04, bit.bxor(b3,b1)));
+    local w = bit.bxor(v,gf.mul(0x04, bit.bxor(b2,b0)));
+    
+    return util.putByte( bit.bxor(bit.bxor(b3,v), gf.mul(0x02, bit.bxor(b0,b3))), 0)
+         + util.putByte( bit.bxor(bit.bxor(b2,w), gf.mul(0x02, t              )), 1)
+         + util.putByte( bit.bxor(bit.bxor(b1,v), gf.mul(0x02, bit.bxor(b0,b3))), 2)
+         + util.putByte( bit.bxor(bit.bxor(b0,w), gf.mul(0x02, u              )), 3);
+end
+
+--
+-- generate key schedule for aes decryption
+--
+-- uses key schedule for aes encryption and transforms each
+-- key by inverse mix column. 
+--
+function public.expandDecryptionKey(key)
+    local keySchedule = public.expandEncryptionKey(key);
+    if (keySchedule == nil) then
+        return nil;
+    end
+    
+    keySchedule[public.KEY_TYPE] = public.DECRYPTION_KEY;    
+
+    for i = 4, (keySchedule[public.ROUNDS] + 1)*4 - 5 do
+        keySchedule[i] = private.invMixColumnOld(keySchedule[i]);
+    end
+    
+    return keySchedule;
+end
+
+--
+-- xor round key to state
+--
+function private.addRoundKey(state, key, round)
+    for i = 0, 3 do
+        state[i] = bit.bxor(state[i], key[round*4+i]);
+    end
+end
+
+--
+-- do encryption round (ShiftRow, SubBytes, MixColumn together)
+--
+function private.doRound(origState, dstState)
+    dstState[0] =  bit.bxor(bit.bxor(bit.bxor(
+                private.table0[util.getByte(origState[0],3)],
+                private.table1[util.getByte(origState[1],2)]),
+                private.table2[util.getByte(origState[2],1)]),
+                private.table3[util.getByte(origState[3],0)]);
+
+    dstState[1] =  bit.bxor(bit.bxor(bit.bxor(
+                private.table0[util.getByte(origState[1],3)],
+                private.table1[util.getByte(origState[2],2)]),
+                private.table2[util.getByte(origState[3],1)]),
+                private.table3[util.getByte(origState[0],0)]);
+    
+    dstState[2] =  bit.bxor(bit.bxor(bit.bxor(
+                private.table0[util.getByte(origState[2],3)],
+                private.table1[util.getByte(origState[3],2)]),
+                private.table2[util.getByte(origState[0],1)]),
+                private.table3[util.getByte(origState[1],0)]);
+    
+    dstState[3] =  bit.bxor(bit.bxor(bit.bxor(
+                private.table0[util.getByte(origState[3],3)],
+                private.table1[util.getByte(origState[0],2)]),
+                private.table2[util.getByte(origState[1],1)]),
+                private.table3[util.getByte(origState[2],0)]);
+end
+
+--
+-- do last encryption round (ShiftRow and SubBytes)
+--
+function private.doLastRound(origState, dstState)
+    dstState[0] = util.putByte(private.SBox[util.getByte(origState[0],3)], 3)
+                + util.putByte(private.SBox[util.getByte(origState[1],2)], 2)
+                + util.putByte(private.SBox[util.getByte(origState[2],1)], 1)
+                + util.putByte(private.SBox[util.getByte(origState[3],0)], 0);
+
+    dstState[1] = util.putByte(private.SBox[util.getByte(origState[1],3)], 3)
+                + util.putByte(private.SBox[util.getByte(origState[2],2)], 2)
+                + util.putByte(private.SBox[util.getByte(origState[3],1)], 1)
+                + util.putByte(private.SBox[util.getByte(origState[0],0)], 0);
+
+    dstState[2] = util.putByte(private.SBox[util.getByte(origState[2],3)], 3)
+                + util.putByte(private.SBox[util.getByte(origState[3],2)], 2)
+                + util.putByte(private.SBox[util.getByte(origState[0],1)], 1)
+                + util.putByte(private.SBox[util.getByte(origState[1],0)], 0);
+
+    dstState[3] = util.putByte(private.SBox[util.getByte(origState[3],3)], 3)
+                + util.putByte(private.SBox[util.getByte(origState[0],2)], 2)
+                + util.putByte(private.SBox[util.getByte(origState[1],1)], 1)
+                + util.putByte(private.SBox[util.getByte(origState[2],0)], 0);
+end
+
+--
+-- do decryption round 
+--
+function private.doInvRound(origState, dstState)
+    dstState[0] =  bit.bxor(bit.bxor(bit.bxor(
+                private.tableInv0[util.getByte(origState[0],3)],
+                private.tableInv1[util.getByte(origState[3],2)]),
+                private.tableInv2[util.getByte(origState[2],1)]),
+                private.tableInv3[util.getByte(origState[1],0)]);
+
+    dstState[1] =  bit.bxor(bit.bxor(bit.bxor(
+                private.tableInv0[util.getByte(origState[1],3)],
+                private.tableInv1[util.getByte(origState[0],2)]),
+                private.tableInv2[util.getByte(origState[3],1)]),
+                private.tableInv3[util.getByte(origState[2],0)]);
+    
+    dstState[2] =  bit.bxor(bit.bxor(bit.bxor(
+                private.tableInv0[util.getByte(origState[2],3)],
+                private.tableInv1[util.getByte(origState[1],2)]),
+                private.tableInv2[util.getByte(origState[0],1)]),
+                private.tableInv3[util.getByte(origState[3],0)]);
+    
+    dstState[3] =  bit.bxor(bit.bxor(bit.bxor(
+                private.tableInv0[util.getByte(origState[3],3)],
+                private.tableInv1[util.getByte(origState[2],2)]),
+                private.tableInv2[util.getByte(origState[1],1)]),
+                private.tableInv3[util.getByte(origState[0],0)]);
+end
+
+--
+-- do last decryption round
+--
+function private.doInvLastRound(origState, dstState)
+    dstState[0] = util.putByte(private.iSBox[util.getByte(origState[0],3)], 3)
+                + util.putByte(private.iSBox[util.getByte(origState[3],2)], 2)
+                + util.putByte(private.iSBox[util.getByte(origState[2],1)], 1)
+                + util.putByte(private.iSBox[util.getByte(origState[1],0)], 0);
+
+    dstState[1] = util.putByte(private.iSBox[util.getByte(origState[1],3)], 3)
+                + util.putByte(private.iSBox[util.getByte(origState[0],2)], 2)
+                + util.putByte(private.iSBox[util.getByte(origState[3],1)], 1)
+                + util.putByte(private.iSBox[util.getByte(origState[2],0)], 0);
+
+    dstState[2] = util.putByte(private.iSBox[util.getByte(origState[2],3)], 3)
+                + util.putByte(private.iSBox[util.getByte(origState[1],2)], 2)
+                + util.putByte(private.iSBox[util.getByte(origState[0],1)], 1)
+                + util.putByte(private.iSBox[util.getByte(origState[3],0)], 0);
+
+    dstState[3] = util.putByte(private.iSBox[util.getByte(origState[3],3)], 3)
+                + util.putByte(private.iSBox[util.getByte(origState[2],2)], 2)
+                + util.putByte(private.iSBox[util.getByte(origState[1],1)], 1)
+                + util.putByte(private.iSBox[util.getByte(origState[0],0)], 0);
+end
+
+--
+-- encrypts 16 Bytes
+-- key           encryption key schedule
+-- input         array with input data
+-- inputOffset   start index for input
+-- output        array for encrypted data
+-- outputOffset  start index for output
+--
+function public.encrypt(key, input, inputOffset, output, outputOffset) 
+    --default parameters
+    inputOffset = inputOffset or 1;
+    output = output or {};
+    outputOffset = outputOffset or 1;
+
+    local state = {};
+    local tmpState = {};
+    
+    if (key[public.KEY_TYPE] ~= public.ENCRYPTION_KEY) then
+        error("No encryption key: "..key[public.KEY_TYPE]);
+        return;
+    end
+
+    state = util.bytesToInts(input, inputOffset, 4);
+    private.addRoundKey(state, key, 0);
+
+    local round = 1;
+    while (round < key[public.ROUNDS] - 1) do
+        -- do a double round to save temporary assignments
+        private.doRound(state, tmpState);
+        private.addRoundKey(tmpState, key, round);
+        round = round + 1;
+
+        private.doRound(tmpState, state);
+        private.addRoundKey(state, key, round);
+        round = round + 1;
+    end
+    
+    private.doRound(state, tmpState);
+    private.addRoundKey(tmpState, key, round);
+    round = round +1;
+
+    private.doLastRound(tmpState, state);
+    private.addRoundKey(state, key, round);
+    
+    return util.intsToBytes(state, output, outputOffset);
+end
+
+--
+-- decrypt 16 bytes
+-- key           decryption key schedule
+-- input         array with input data
+-- inputOffset   start index for input
+-- output        array for decrypted data
+-- outputOffset  start index for output
+---
+function public.decrypt(key, input, inputOffset, output, outputOffset) 
+    -- default arguments
+    inputOffset = inputOffset or 1;
+    output = output or {};
+    outputOffset = outputOffset or 1;
+
+    local state = {};
+    local tmpState = {};
+
+    if (key[public.KEY_TYPE] ~= public.DECRYPTION_KEY) then
+        error("No decryption key: "..key[public.KEY_TYPE]);
+        return;
+    end
+
+    state = util.bytesToInts(input, inputOffset, 4);
+    private.addRoundKey(state, key, key[public.ROUNDS]);
+
+    local round = key[public.ROUNDS] - 1;
+    while (round > 2) do
+        -- do a double round to save temporary assignments
+        private.doInvRound(state, tmpState);
+        private.addRoundKey(tmpState, key, round);
+        round = round - 1;
+
+        private.doInvRound(tmpState, state);
+        private.addRoundKey(state, key, round);
+        round = round - 1;
+    end
+    
+    private.doInvRound(state, tmpState);
+    private.addRoundKey(tmpState, key, round);
+    round = round - 1;
+
+    private.doInvLastRound(tmpState, state);
+    private.addRoundKey(state, key, round);
+    
+    return util.intsToBytes(state, output, outputOffset);
+end
+
+-- calculate all tables when loading this file
+private.calcSBox();
+private.calcRoundTables();
+private.calcInvRoundTables();
+
+return public;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aeslua/buffer.lua	Wed Feb 16 20:29:33 2011 +0000
@@ -0,0 +1,27 @@
+local public = {};
+
+local aeslua = require("aeslua");
+aeslua.buffer = public;
+
+function public.new ()
+  return {};
+end
+
+function public.addString (stack, s)
+  table.insert(stack, s)
+  for i = #stack - 1, 1, -1 do
+    if #stack[i] > #stack[i+1] then 
+        break;
+    end
+    stack[i] = stack[i] .. table.remove(stack);
+  end
+end
+
+function public.toString (stack)
+  for i = #stack - 1, 1, -1 do
+    stack[i] = stack[i] .. table.remove(stack);
+  end
+  return stack[1];
+end
+
+return public;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aeslua/ciphermode.lua	Wed Feb 16 20:29:33 2011 +0000
@@ -0,0 +1,148 @@
+local aes = require("aeslua.aes");
+local util = require("aeslua.util");
+local buffer = require("aeslua.buffer");
+
+local public = {};
+
+local aeslua = require("aeslua");
+aeslua.ciphermode = public;
+
+--
+-- Encrypt strings
+-- key - byte array with key
+-- string - string to encrypt
+-- modefunction - function for cipher mode to use
+--
+function public.encryptString(key, data, modeFunction)
+    local iv = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+    local keySched = aes.expandEncryptionKey(key);
+    local encryptedData = buffer.new();
+    
+    for i = 1, #data/16 do
+        local offset = (i-1)*16 + 1;
+        local byteData = {string.byte(data,offset,offset +15)};
+		
+        modeFunction(keySched, byteData, iv);
+
+        buffer.addString(encryptedData, string.char(unpack(byteData)));    
+    end
+    
+    return buffer.toString(encryptedData);
+end
+
+--
+-- the following 4 functions can be used as 
+-- modefunction for encryptString
+--
+
+-- Electronic code book mode encrypt function
+function public.encryptECB(keySched, byteData, iv) 
+	aes.encrypt(keySched, byteData, 1, byteData, 1);
+end
+
+-- Cipher block chaining mode encrypt function
+function public.encryptCBC(keySched, byteData, iv) 
+    util.xorIV(byteData, iv);
+
+    aes.encrypt(keySched, byteData, 1, byteData, 1);    
+        
+    for j = 1,16 do
+        iv[j] = byteData[j];
+    end
+end
+
+-- Output feedback mode encrypt function
+function public.encryptOFB(keySched, byteData, iv) 
+    aes.encrypt(keySched, iv, 1, iv, 1);
+    util.xorIV(byteData, iv);
+end
+
+-- Cipher feedback mode encrypt function
+function public.encryptCFB(keySched, byteData, iv) 
+    aes.encrypt(keySched, iv, 1, iv, 1);    
+    util.xorIV(byteData, iv);
+       
+    for j = 1,16 do
+        iv[j] = byteData[j];
+    end        
+end
+
+--
+-- Decrypt strings
+-- key - byte array with key
+-- string - string to decrypt
+-- modefunction - function for cipher mode to use
+--
+function public.decryptString(key, data, modeFunction)
+    local iv = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+    
+    local keySched;
+    if (modeFunction == public.decryptOFB or modeFunction == public.decryptCFB) then
+    	keySched = aes.expandEncryptionKey(key);
+   	else
+   		keySched = aes.expandDecryptionKey(key);
+    end
+    
+    local decryptedData = buffer.new();
+
+    for i = 1, #data/16 do
+        local offset = (i-1)*16 + 1;
+        local byteData = {string.byte(data,offset,offset +15)};
+
+		iv = modeFunction(keySched, byteData, iv);
+
+        buffer.addString(decryptedData, string.char(unpack(byteData)));
+    end
+
+    return buffer.toString(decryptedData);    
+end
+
+--
+-- the following 4 functions can be used as 
+-- modefunction for decryptString
+--
+
+-- Electronic code book mode decrypt function
+function public.decryptECB(keySched, byteData, iv) 
+
+    aes.decrypt(keySched, byteData, 1, byteData, 1);
+    
+    return iv;
+end
+
+-- Cipher block chaining mode decrypt function
+function public.decryptCBC(keySched, byteData, iv) 
+	local nextIV = {};
+    for j = 1,16 do
+        nextIV[j] = byteData[j];
+    end
+        
+    aes.decrypt(keySched, byteData, 1, byteData, 1);    
+    util.xorIV(byteData, iv);
+
+	return nextIV;
+end
+
+-- Output feedback mode decrypt function
+function public.decryptOFB(keySched, byteData, iv) 
+    aes.encrypt(keySched, iv, 1, iv, 1);
+    util.xorIV(byteData, iv);
+    
+    return iv;
+end
+
+-- Cipher feedback mode decrypt function
+function public.decryptCFB(keySched, byteData, iv) 
+    local nextIV = {};
+    for j = 1,16 do
+        nextIV[j] = byteData[j];
+    end
+
+    aes.encrypt(keySched, iv, 1, iv, 1);
+        
+    util.xorIV(byteData, iv);
+    
+    return nextIV;
+end
+
+return public;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aeslua/gf.lua	Wed Feb 16 20:29:33 2011 +0000
@@ -0,0 +1,117 @@
+local bit = require("bit");
+
+-- finite field with base 2 and modulo irreducible polynom x^8+x^4+x^3+x+1 = 0x11d
+local private = {};
+local public = {};
+
+local aeslua = require("aeslua");
+aeslua.gf = public;
+
+-- private data of gf
+private.n = 0x100;
+private.ord = 0xff;
+private.irrPolynom = 0x11b;
+private.exp = {};
+private.log = {};
+
+--
+-- add two polynoms (its simply xor)
+--
+function public.add(operand1, operand2) 
+	return bit.bxor(operand1,operand2);
+end
+
+-- 
+-- subtract two polynoms (same as addition)
+--
+function public.sub(operand1, operand2) 
+	return bit.bxor(operand1,operand2);
+end
+
+--
+-- inverts element
+-- a^(-1) = g^(order - log(a))
+--
+function public.invert(operand)
+	-- special case for 1 
+	if (operand == 1) then
+		return 1;
+	end;
+	-- normal invert
+	local exponent = private.ord - private.log[operand];
+	return private.exp[exponent];
+end
+
+--
+-- multiply two elements using a logarithm table
+-- a*b = g^(log(a)+log(b))
+--
+function public.mul(operand1, operand2)
+    if (operand1 == 0 or operand2 == 0) then
+        return 0;
+    end
+	
+    local exponent = private.log[operand1] + private.log[operand2];
+	if (exponent >= private.ord) then
+		exponent = exponent - private.ord;
+	end
+	return  private.exp[exponent];
+end
+
+--
+-- divide two elements
+-- a/b = g^(log(a)-log(b))
+--
+function public.div(operand1, operand2)
+    if (operand1 == 0)  then
+        return 0;
+    end
+    -- TODO: exception if operand2 == 0
+	local exponent = private.log[operand1] - private.log[operand2];
+	if (exponent < 0) then
+		exponent = exponent + private.ord;
+	end
+	return private.exp[exponent];
+end
+
+--
+-- print logarithmic table
+--
+function public.printLog()
+	for i = 1, private.n do
+		print("log(", i-1, ")=", private.log[i-1]);
+	end
+end
+
+--
+-- print exponentiation table
+--
+function public.printExp()
+	for i = 1, private.n do
+		print("exp(", i-1, ")=", private.exp[i-1]);
+	end
+end
+
+--
+-- calculate logarithmic and exponentiation table
+--
+function private.initMulTable()
+	local a = 1;
+
+	for i = 0,private.ord-1 do
+    	private.exp[i] = a;
+		private.log[a] = i;
+
+		-- multiply with generator x+1 -> left shift + 1	
+		a = bit.bxor(bit.lshift(a, 1), a);
+
+		-- if a gets larger than order, reduce modulo irreducible polynom
+		if a > private.ord then
+			a = public.sub(a, private.irrPolynom);
+		end
+	end
+end
+
+private.initMulTable();
+
+return public;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aeslua/init.lua	Wed Feb 16 20:29:33 2011 +0000
@@ -0,0 +1,3 @@
+local aeslua = {};
+package.loaded.aeslua = aeslua;
+return aeslua;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aeslua/util.lua	Wed Feb 16 20:29:33 2011 +0000
@@ -0,0 +1,155 @@
+local bit = require("bit");
+
+local public = {};
+local private = {};
+
+local aeslua = require("aeslua");
+aeslua.util = public;
+
+--
+-- calculate the parity of one byte
+--
+function public.byteParity(byte)
+    byte = bit.bxor(byte, bit.rshift(byte, 4));
+    byte = bit.bxor(byte, bit.rshift(byte, 2));
+    byte = bit.bxor(byte, bit.rshift(byte, 1));
+    return bit.band(byte, 1);
+end
+
+-- 
+-- get byte at position index
+--
+function public.getByte(number, index)
+    if (index == 0) then
+        return bit.band(number,0xff);
+    else
+        return bit.band(bit.rshift(number, index*8),0xff);
+    end
+end
+
+
+--
+-- put number into int at position index
+--
+function public.putByte(number, index)
+    if (index == 0) then
+        return bit.band(number,0xff);
+    else
+        return bit.lshift(bit.band(number,0xff),index*8);
+    end
+end
+
+--
+-- convert byte array to int array
+--
+function public.bytesToInts(bytes, start, n)
+    local ints = {};
+    for i = 0, n - 1 do
+        ints[i] = public.putByte(bytes[start + (i*4)    ], 3)
+                + public.putByte(bytes[start + (i*4) + 1], 2) 
+                + public.putByte(bytes[start + (i*4) + 2], 1)    
+                + public.putByte(bytes[start + (i*4) + 3], 0);
+    end
+    return ints;
+end
+
+--
+-- convert int array to byte array
+--
+function public.intsToBytes(ints, output, outputOffset, n)
+    n = n or #ints;
+    for i = 0, n do
+        for j = 0,3 do
+            output[outputOffset + i*4 + (3 - j)] = public.getByte(ints[i], j);
+        end
+    end
+    return output;
+end
+
+--
+-- convert bytes to hexString
+--
+function private.bytesToHex(bytes)
+    local hexBytes = "";
+    
+    for i,byte in ipairs(bytes) do 
+        hexBytes = hexBytes .. string.format("%02x ", byte);
+    end
+
+    return hexBytes;
+end
+
+--
+-- convert data to hex string
+--
+function public.toHexString(data)
+    local type = type(data);
+    if (type == "number") then
+        return string.format("%08x",data);
+    elseif (type == "table") then
+        return private.bytesToHex(data);
+    elseif (type == "string") then
+        local bytes = {string.byte(data, 1, #data)}; 
+
+        return private.bytesToHex(bytes);
+    else
+        return data;
+    end
+end
+
+function public.padByteString(data)
+    local dataLength = #data;
+    
+    local random1 = math.random(0,255);
+    local random2 = math.random(0,255);
+
+    local prefix = string.char(random1,
+                               random2,
+                               random1,
+                               random2,
+                               public.getByte(dataLength, 3),
+                               public.getByte(dataLength, 2),
+                               public.getByte(dataLength, 1),
+                               public.getByte(dataLength, 0));
+
+    data = prefix .. data;
+
+    local paddingLength = math.ceil(#data/16)*16 - #data;
+    local padding = "";
+    for i=1,paddingLength do
+        padding = padding .. string.char(math.random(0,255));
+    end 
+
+    return data .. padding;
+end
+
+function private.properlyDecrypted(data)
+    local random = {string.byte(data,1,4)};
+
+    if (random[1] == random[3] and random[2] == random[4]) then
+        return true;
+    end
+    
+    return false;
+end
+
+function public.unpadByteString(data)
+    if (not private.properlyDecrypted(data)) then
+        return nil;
+    end
+
+    local dataLength = public.putByte(string.byte(data,5), 3)
+                     + public.putByte(string.byte(data,6), 2) 
+                     + public.putByte(string.byte(data,7), 1)    
+                     + public.putByte(string.byte(data,8), 0);
+    
+    return string.sub(data,9,8+dataLength);
+end
+
+function public.xorIV(data, iv)
+    for i = 1,16 do
+        data[i] = bit.bxor(data[i], iv[i]);
+    end 
+end
+
+return public;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crc16/crc16.lua	Wed Feb 16 20:29:33 2011 +0000
@@ -0,0 +1,33 @@
+local bit = require "bit";
+
+module "crc16"
+
+function hash(str)
+	local crc;
+	
+	local function initCrc()
+		crc = 0xffff;
+	end
+	
+	local function updCrc(byte)
+		crc = bit.bxor(crc, byte);
+		for i=1,8 do
+			local j = bit.band(crc, 1);
+			crc = bit.rshift(crc, 1);
+			if j ~= 0 then
+				crc = bit.bxor(crc, 0x8408);
+			end
+		end
+	end
+
+	local function getCrc(str)
+		initCrc();
+		for i = 1, #str  do
+			updCrc(str:byte(i));
+		end
+		return crc;
+	end
+	return getCrc(str);
+end
+
+return { hash = hash }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/squishy	Wed Feb 16 20:29:33 2011 +0000
@@ -0,0 +1,12 @@
+Module "aeslua" "aeslua/init.lua"
+Module "aeslua.ciphermode" "aeslua/ciphermode.lua"
+Module "aeslua.aes" "aeslua/aes.lua"
+Module "aeslua.util" "aeslua/util.lua"
+Module "aeslua.buffer" "aeslua/buffer.lua"
+Module "aeslua.gf" "aeslua/gf.lua"
+
+Module "crc16" "crc16/crc16.lua"
+
+Main "yubikey/init.lua"
+
+Output "yubikey.lua"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/yubikey/init.lua	Wed Feb 16 20:29:33 2011 +0000
@@ -0,0 +1,124 @@
+local _M = {};
+
+local aeslua = require "aeslua";
+local ciphermode = require "aeslua.ciphermode";
+local crc16 = require "crc16";
+
+local modhex2hex;
+do
+	local modhex_map = {};
+	local modhex_chars = "cbdefghijklnrtuv";
+	for i=1,16 do
+		modhex_map[modhex_chars:sub(i,i)] = ("%x"):format(i-1);
+	end
+	function modhex2hex(modhex)
+		if modhex then
+			return (modhex:gsub(".", modhex_map));
+		end
+	end
+end
+_M.modhex2hex = modhex2hex;
+
+local function hex2bin(hex)
+	if hex then
+		return (hex:gsub("..", function (c) return string.char(tonumber(c, 16)); end));
+	end
+end
+_M.hex2bin = hex2bin;
+
+local function bin2hex(bin)
+	if bin then
+		return (bin:gsub(".", function (b) return ("%02x"):format(b:byte()); end));
+	end
+end
+_M.bin2hex = bin2hex;
+
+local otp_parser = {};
+local otp_parser_mt = { __index = otp_parser };
+
+function _M.new_fetch_key_hex(fetchkeyhex)
+	return function (...) return hex2bin(fetchkeyhex(...)); end
+end
+
+function _M.new_otp_parser(config)
+	return setmetatable({
+		config = config,
+	}, otp_parser_mt);
+end
+
+function otp_parser:parse(otp, key)
+	-- Password is any extra data before the real OTP
+	local password;
+	if #otp > 32 + self.config.prefix_length then
+		password = otp:sub(1, #otp - (32 + self.config.prefix_length));
+		otp = otp:sub(#password+1);
+	end
+	local prefix = otp:sub(1, self.config.prefix_length);
+	local token = otp:sub(#prefix+1);
+	if not key then
+		key = self.config.fetch_key(prefix);
+	else
+		key = hex2bin(key);
+	end
+	if not key then return false, "no-key"; end
+	key = {key:byte(1,#key)}
+	local decrypted = ciphermode.decryptString(key, hex2bin(modhex2hex(token)), ciphermode.decryptCBC);
+	if not decrypted then return false, "decrypt-failed"; end
+	-- Extract private UID
+	local uid = decrypted:sub(1,6);
+	-- Build insertion counter (2 bytes)
+	local use1, use2 = decrypted:sub(7,8):byte(1,2);
+	local use_ctr = use1 + math.pow(2, 8)*use2;
+	-- Build timestamp (3 bytes)
+	local time1, time2, time3 = decrypted:sub(9,11):byte(1,3);
+	local timestamp = time1 + math.pow(2,8)*time2 + math.pow(2, 16)*time3;
+	-- Extract session counter (1 byte)
+	local session_ctr = decrypted:sub(12, 12):byte();
+	
+	if crc16.hash(decrypted) ~= 0xf0b8 then
+		return false, "invalid-checksum";
+	end
+	
+	-- Return parsed fields
+	return true, {
+		password = password;
+		public_id = prefix;
+		token = token;
+		private_id = bin2hex(uid);
+		session_counter = session_ctr;
+		use_counter = use_ctr;
+		timestamp = timestamp;
+	};
+end
+
+function _M.new_authenticator(config)
+	local parser = _M.new_otp_parser(config);
+	local function authenticate(self, otp, key, device_info, userdata)
+		-- Parse OTP, get device data (from config callback)
+		local ok, ret = parser:parse(otp, key);
+		if not ok then return ok, ret; end
+		
+		if not device_info then
+			device_info = config.fetch_device_info(ret);
+		end
+		
+		if ret.use_counter < (device_info.use_counter or 0)
+		or ((ret.use_counter == (device_info.use_counter or 0))
+		  and (ret.session_counter <= (device_info.session_counter or 0))) then
+			return false, "otp-already-used";
+		end
+		
+		local authed, err = config.check_credentials(ret, device_info, userdata);
+		if not authed then return authed, err; end
+		
+		device_info.use_counter = ret.use_counter;
+		device_info.session_counter = ret.session_counter;
+		
+		config.store_device_info(device_info, userdata);
+		
+		return true, ret;
+	end
+	return { authenticate = authenticate };
+end
+
+return _M;

mercurial